"""Support for simplified access to data on nodes of type omni.graph.action.OnMouseInput

Event node which fires when a mouse event occurs.
 You can choose which mouse element this node reacts to. When mouse element
is chosen to be a button, the only meaningful outputs are: outputs:pressed, outputs:released and outputs:isPressed. When
scroll or move events are chosen, the only meaningful outputs are: outputs:valueChanged and outputs:value. You can choose
to output normalized or pixel coordinates of the mouse.
 Pixel coordinates are the absolute position of the mouse cursor
in pixel unit. The original point is the upper left corner. The minimum value is 0, and the maximum value depends on the
size of the window.
 Normalized coordinates are the relative position of the mouse cursor to the window. The value is always
between 0 and 1.
"""

import numpy

import omni.graph.core as og
import omni.graph.core._omni_graph_core as _og
import omni.graph.tools.ogn as ogn



class OgnOnMouseInputDatabase(og.Database):
    """Helper class providing simplified access to data on nodes of type omni.graph.action.OnMouseInput

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.mouseElement
            inputs.onlyPlayback
        Outputs:
            outputs.isPressed
            outputs.pressed
            outputs.released
            outputs.value
            outputs.valueChanged

    Predefined Tokens:
        tokens.LeftButton
        tokens.MiddleButton
        tokens.RightButton
        tokens.NormalizedMove
        tokens.PixelMove
        tokens.Scroll
    """

    # Imprint the generator and target ABI versions in the file for JIT generation
    GENERATOR_VERSION = (1, 41, 3)
    TARGET_VERSION = (2, 139, 12)

    # This is an internal object that provides per-class storage of a per-node data dictionary
    PER_NODE_DATA = {}

    # This is an internal object that describes unchanging attributes in a generic way
    # The values in this list are in no particular order, as a per-attribute tuple
    #     Name, Type, ExtendedTypeIndex, UiName, Description, Metadata,
    #     Is_Required, DefaultValue, Is_Deprecated, DeprecationMsg
    # You should not need to access any of this data directly, use the defined database interfaces
    INTERFACE = og.Database._get_interface([
        ('inputs:mouseElement', 'token', 0, 'Mouse Element', 'The event to trigger the downstream execution ', {'displayGroup': 'parameters', ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.ALLOWED_TOKENS: 'Left Button,Middle Button,Right Button,Normalized Move,Pixel Move,Scroll', ogn.MetadataKeys.ALLOWED_TOKENS_RAW: '{"LeftButton": "Left Button", "MiddleButton": "Middle Button", "RightButton": "Right Button", "NormalizedMove": "Normalized Move", "PixelMove": "Pixel Move", "Scroll": "Scroll"}', ogn.MetadataKeys.DEFAULT: '"Left Button"'}, True, "Left Button", False, ''),
        ('inputs:onlyPlayback', 'bool', 0, 'Only Simulate On Play', 'When true, the node is only computed while Stage is being played.', {ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.DEFAULT: 'true'}, True, True, False, ''),
        ('outputs:isPressed', 'bool', 0, None, 'True if the mouse button was pressed, False if it was released or mouse element is not related to a button', {}, True, None, False, ''),
        ('outputs:pressed', 'execution', 0, 'Pressed', 'Executes when mouse button was pressed. Will not execute on move or scroll events', {}, True, None, False, ''),
        ('outputs:released', 'execution', 0, 'Released', 'Executes when mouse button was released. Will not execute on move or scroll events', {}, True, None, False, ''),
        ('outputs:value', 'float2', 0, 'Delta Value', 'The meaning of this output depends on Event In.\nNormalized Move: will output the normalized coordinates of mouse, each element of the vector is in the range of [0, 1]\nPixel Move: will output the absolute coordinates of mouse, each vector is in the range of [0, pixel width/height of the window]\nScroll: will output the change of scroll value\nOtherwise: will output [0,0]', {}, True, None, False, ''),
        ('outputs:valueChanged', 'execution', 0, 'Moved', 'Executes when user moves the cursor or scrolls the cursor. Will not execute on button events', {}, True, None, False, ''),
    ])

    class tokens:
        LeftButton = "Left Button"
        MiddleButton = "Middle Button"
        RightButton = "Right Button"
        NormalizedMove = "Normalized Move"
        PixelMove = "Pixel Move"
        Scroll = "Scroll"

    @classmethod
    def _populate_role_data(cls):
        """Populate a role structure with the non-default roles on this node type"""
        role_data = super()._populate_role_data()
        role_data.outputs.pressed = og.AttributeRole.EXECUTION
        role_data.outputs.released = og.AttributeRole.EXECUTION
        role_data.outputs.valueChanged = og.AttributeRole.EXECUTION
        return role_data

    class ValuesForInputs(og.DynamicAttributeAccess):
        LOCAL_PROPERTY_NAMES = { }
        """Helper class that creates natural hierarchical access to input attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)
            self._batchedReadAttributes = []
            self._batchedReadValues = []

        @property
        def mouseElement(self):
            data_view = og.AttributeValueHelper(self._attributes.mouseElement)
            return data_view.get()

        @mouseElement.setter
        def mouseElement(self, value):
            if self._setting_locked:
                raise og.ReadOnlyError(self._attributes.mouseElement)
            data_view = og.AttributeValueHelper(self._attributes.mouseElement)
            data_view.set(value)

        @property
        def onlyPlayback(self):
            data_view = og.AttributeValueHelper(self._attributes.onlyPlayback)
            return data_view.get()

        @onlyPlayback.setter
        def onlyPlayback(self, value):
            if self._setting_locked:
                raise og.ReadOnlyError(self._attributes.onlyPlayback)
            data_view = og.AttributeValueHelper(self._attributes.onlyPlayback)
            data_view.set(value)

        def _prefetch(self):
            readAttributes = self._batchedReadAttributes
            newValues = _og._prefetch_input_attributes_data(readAttributes)
            if len(readAttributes) == len(newValues):
                self._batchedReadValues = newValues

    class ValuesForOutputs(og.DynamicAttributeAccess):
        LOCAL_PROPERTY_NAMES = { }
        """Helper class that creates natural hierarchical access to output attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)
            self._batchedWriteValues = { }

        @property
        def isPressed(self):
            data_view = og.AttributeValueHelper(self._attributes.isPressed)
            return data_view.get()

        @isPressed.setter
        def isPressed(self, value):
            data_view = og.AttributeValueHelper(self._attributes.isPressed)
            data_view.set(value)

        @property
        def pressed(self):
            data_view = og.AttributeValueHelper(self._attributes.pressed)
            return data_view.get()

        @pressed.setter
        def pressed(self, value):
            data_view = og.AttributeValueHelper(self._attributes.pressed)
            data_view.set(value)

        @property
        def released(self):
            data_view = og.AttributeValueHelper(self._attributes.released)
            return data_view.get()

        @released.setter
        def released(self, value):
            data_view = og.AttributeValueHelper(self._attributes.released)
            data_view.set(value)

        @property
        def value(self):
            data_view = og.AttributeValueHelper(self._attributes.value)
            return data_view.get()

        @value.setter
        def value(self, value):
            data_view = og.AttributeValueHelper(self._attributes.value)
            data_view.set(value)

        @property
        def valueChanged(self):
            data_view = og.AttributeValueHelper(self._attributes.valueChanged)
            return data_view.get()

        @valueChanged.setter
        def valueChanged(self, value):
            data_view = og.AttributeValueHelper(self._attributes.valueChanged)
            data_view.set(value)

        def _commit(self):
            _og._commit_output_attributes_data(self._batchedWriteValues)
            self._batchedWriteValues = { }

    class ValuesForState(og.DynamicAttributeAccess):
        """Helper class that creates natural hierarchical access to state attributes"""
        def __init__(self, node: og.Node, attributes, dynamic_attributes: og.DynamicAttributeInterface):
            """Initialize simplified access for the attribute data"""
            context = node.get_graph().get_default_graph_context()
            super().__init__(context, node, attributes, dynamic_attributes)

    def __init__(self, node):
        super().__init__(node)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_INPUT)
        self.inputs = OgnOnMouseInputDatabase.ValuesForInputs(node, self.attributes.inputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_OUTPUT)
        self.outputs = OgnOnMouseInputDatabase.ValuesForOutputs(node, self.attributes.outputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_STATE)
        self.state = OgnOnMouseInputDatabase.ValuesForState(node, self.attributes.state, dynamic_attributes)
