"""Support for simplified access to data on nodes of type omni.graph.ui_nodes.OnPicked

Event node which fires when a picking event occurs in the specified viewport. Note that picking events must be enabled on
the specified viewport using a SetViewportMode node.
"""

import numpy
import usdrt

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



class OgnOnPickedDatabase(og.Database):
    """Helper class providing simplified access to data on nodes of type omni.graph.ui_nodes.OnPicked

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.gesture
            inputs.onlyPlayback
            inputs.trackedPrims
            inputs.viewport
        Outputs:
            outputs.isTrackedPrimPicked
            outputs.missed
            outputs.picked
            outputs.pickedPrim
            outputs.pickedPrimPath
            outputs.pickedWorldPos
            outputs.trackedPrimPaths

    Predefined Tokens:
        tokens.LeftMouseClick
        tokens.RightMouseClick
        tokens.MiddleMouseClick
        tokens.LeftMousePress
        tokens.RightMousePress
        tokens.MiddleMousePress
    """

    # 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:gesture', 'token', 0, 'Gesture', 'The input gesture to trigger a picking event', {'displayGroup': 'parameters', ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.ALLOWED_TOKENS: 'Left Mouse Click,Right Mouse Click,Middle Mouse Click,Left Mouse Press,Right Mouse Press,Middle Mouse Press', ogn.MetadataKeys.ALLOWED_TOKENS_RAW: '{"LeftMouseClick": "Left Mouse Click", "RightMouseClick": "Right Mouse Click", "MiddleMouseClick": "Middle Mouse Click", "LeftMousePress": "Left Mouse Press", "RightMousePress": "Right Mouse Press", "MiddleMousePress": "Middle Mouse Press"}', ogn.MetadataKeys.DEFAULT: '"Left Mouse Click"'}, True, "Left Mouse Click", 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, ''),
        ('inputs:trackedPrims', 'target', 0, 'Tracked Prims', "Optionally specify a set of tracked prims that will cause 'Picked' to fire when picked", {ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.ALLOW_MULTI_INPUTS: '1'}, False, [], False, ''),
        ('inputs:viewport', 'token', 0, 'Viewport', 'Name of the viewport window to watch for picking events', {ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.DEFAULT: '"Viewport"'}, True, "Viewport", False, ''),
        ('outputs:isTrackedPrimPicked', 'bool', 0, 'Is Tracked Prim Picked', "True if a tracked prim got picked, or if any prim got picked if no tracked prims are specified\n(will always be true when 'Picked' fires, and false when 'Missed' fires)", {}, True, None, False, ''),
        ('outputs:missed', 'execution', 0, 'Missed', 'Enabled when an attempted picking did not pick a tracked prim,\nor when nothing gets picked if no tracked prims are specified', {}, True, None, False, ''),
        ('outputs:picked', 'execution', 0, 'Picked', 'Enabled when a tracked prim is picked,\nor when any prim is picked if no tracked prims are specified', {}, True, None, False, ''),
        ('outputs:pickedPrim', 'target', 0, 'Picked Prim', 'The picked prim, or an empty target if nothing got picked', {}, True, [], False, ''),
        ('outputs:pickedPrimPath', 'token', 0, 'Picked Prim Path', 'The path of the picked prim, or an empty string if nothing got picked', {}, True, None, True, 'Use the pickedPrim output instead'),
        ('outputs:pickedWorldPos', 'point3d', 0, 'Picked World Position', 'The XYZ-coordinates of the point in world space at which the prim got picked,\nor (0,0,0) if nothing got picked', {}, True, None, False, ''),
        ('outputs:trackedPrimPaths', 'token[]', 0, 'Tracked Prim Paths', "A list of the paths of the prims specified in 'Tracked Prims'", {}, True, None, False, ''),
    ])

    class tokens:
        LeftMouseClick = "Left Mouse Click"
        RightMouseClick = "Right Mouse Click"
        MiddleMouseClick = "Middle Mouse Click"
        LeftMousePress = "Left Mouse Press"
        RightMousePress = "Right Mouse Press"
        MiddleMousePress = "Middle Mouse Press"

    @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.inputs.trackedPrims = og.AttributeRole.TARGET
        role_data.outputs.missed = og.AttributeRole.EXECUTION
        role_data.outputs.picked = og.AttributeRole.EXECUTION
        role_data.outputs.pickedPrim = og.AttributeRole.TARGET
        role_data.outputs.pickedWorldPos = og.AttributeRole.POSITION
        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 gesture(self):
            data_view = og.AttributeValueHelper(self._attributes.gesture)
            return data_view.get()

        @gesture.setter
        def gesture(self, value):
            if self._setting_locked:
                raise og.ReadOnlyError(self._attributes.gesture)
            data_view = og.AttributeValueHelper(self._attributes.gesture)
            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)

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

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

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

        @viewport.setter
        def viewport(self, value):
            if self._setting_locked:
                raise og.ReadOnlyError(self._attributes.viewport)
            data_view = og.AttributeValueHelper(self._attributes.viewport)
            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.pickedPrim_size = None
            self.trackedPrimPaths_size = None
            self._batchedWriteValues = { }

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

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

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

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

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

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

        @property
        def pickedPrim(self):
            data_view = og.AttributeValueHelper(self._attributes.pickedPrim)
            return data_view.get(reserved_element_count=self.pickedPrim_size)

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

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

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

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

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

        @property
        def trackedPrimPaths(self):
            data_view = og.AttributeValueHelper(self._attributes.trackedPrimPaths)
            return data_view.get(reserved_element_count=self.trackedPrimPaths_size)

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

        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 = OgnOnPickedDatabase.ValuesForInputs(node, self.attributes.inputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_OUTPUT)
        self.outputs = OgnOnPickedDatabase.ValuesForOutputs(node, self.attributes.outputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_STATE)
        self.state = OgnOnPickedDatabase.ValuesForState(node, self.attributes.state, dynamic_attributes)
