"""Support for simplified access to data on nodes of type omni.graph.ui.ReadPickState

Read the state of the last picking event from the specified viewport. Note that picking events must be enabled on the specified
viewport using a SetViewportMode node.
"""

import omni.graph.core as og
import omni.graph.core._omni_graph_core as _og
import omni.graph.tools.ogn as ogn
import carb
import numpy
class OgnReadPickStateDatabase(og.Database):
    """Helper class providing simplified access to data on nodes of type omni.graph.ui.ReadPickState

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.gesture
            inputs.trackedPrimPaths
            inputs.trackedPrims
            inputs.usePaths
            inputs.viewport
        Outputs:
            outputs.isTrackedPrimPicked
            outputs.isValid
            outputs.pickedPrimPath
            outputs.pickedWorldPos

    Predefined Tokens:
        tokens.LeftMouseClick
        tokens.RightMouseClick
        tokens.MiddleMouseClick
        tokens.LeftMousePress
        tokens.RightMousePress
        tokens.MiddleMousePress
    """
    # 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.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:trackedPrimPaths', 'token[]', 0, 'Tracked Prim Paths', "Optionally specify a set of prims (by paths) to track whether or not they got picked\n(only affects the value of 'Is Tracked Prim Picked')", {}, False, None, False, ''),
        ('inputs:trackedPrims', 'bundle', 0, 'Tracked Prims', "Optionally specify a set of prims to track whether or not they got picked\n(only affects the value of 'Is Tracked Prim Picked')", {}, False, None, False, ''),
        ('inputs:usePaths', 'bool', 0, 'Use Paths', "When true, 'Tracked Prim Paths' is used, otherwise 'Tracked Prims' is used", {ogn.MetadataKeys.DEFAULT: 'false'}, True, False, False, ''),
        ('inputs:viewport', 'token', 0, 'Viewport', 'Name of the viewport window to watch for picking events', {ogn.MetadataKeys.DEFAULT: '"Viewport"'}, True, 'Viewport', False, ''),
        ('outputs:isTrackedPrimPicked', 'bool', 0, 'Is Tracked Prim Picked', 'True if a tracked prim got picked in the last picking event,\nor if any prim got picked if no tracked prims are specified', {}, True, None, False, ''),
        ('outputs:isValid', 'bool', 0, 'Is Valid', 'True if a valid event state was detected and the outputs of this node are valid, and false otherwise', {}, True, None, False, ''),
        ('outputs:pickedPrimPath', 'token', 0, 'Picked Prim Path', 'The path of the prim picked in the last picking event, or an empty string if nothing got picked', {}, True, None, False, ''),
        ('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, ''),
    ])
    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.Database.ROLE_BUNDLE
        role_data.outputs.pickedWorldPos = og.Database.ROLE_POINT
        return role_data
    class ValuesForInputs(og.DynamicAttributeAccess):
        LOCAL_PROPERTY_NAMES = {"gesture", "usePaths", "viewport", "_setting_locked", "_batchedReadAttributes", "_batchedReadValues"}
        """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.__bundles = og.BundleContainer(context, node, attributes, [], read_only=True, gpu_ptr_kinds={})
            self._batchedReadAttributes = [self._attributes.gesture, self._attributes.usePaths, self._attributes.viewport]
            self._batchedReadValues = ["Left Mouse Click", False, "Viewport"]

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

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

        @property
        def trackedPrims(self) -> og.BundleContents:
            """Get the bundle wrapper class for the attribute inputs.trackedPrims"""
            return self.__bundles.trackedPrims

        @property
        def gesture(self):
            return self._batchedReadValues[0]

        @gesture.setter
        def gesture(self, value):
            self._batchedReadValues[0] = value

        @property
        def usePaths(self):
            return self._batchedReadValues[1]

        @usePaths.setter
        def usePaths(self, value):
            self._batchedReadValues[1] = value

        @property
        def viewport(self):
            return self._batchedReadValues[2]

        @viewport.setter
        def viewport(self, value):
            self._batchedReadValues[2] = value

        def __getattr__(self, item: str):
            if item in self.LOCAL_PROPERTY_NAMES:
                return object.__getattribute__(self, item)
            else:
                return super().__getattr__(item)

        def __setattr__(self, item: str, new_value):
            if item in self.LOCAL_PROPERTY_NAMES:
                object.__setattr__(self, item, new_value)
            else:
                super().__setattr__(item, new_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 = {"isTrackedPrimPicked", "isValid", "pickedPrimPath", "pickedWorldPos", "_batchedWriteValues"}
        """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 isTrackedPrimPicked(self):
            value = self._batchedWriteValues.get(self._attributes.isTrackedPrimPicked)
            if value:
                return value
            else:
                data_view = og.AttributeValueHelper(self._attributes.isTrackedPrimPicked)
                return data_view.get()

        @isTrackedPrimPicked.setter
        def isTrackedPrimPicked(self, value):
            self._batchedWriteValues[self._attributes.isTrackedPrimPicked] = value

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

        @isValid.setter
        def isValid(self, value):
            self._batchedWriteValues[self._attributes.isValid] = value

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

        @pickedPrimPath.setter
        def pickedPrimPath(self, value):
            self._batchedWriteValues[self._attributes.pickedPrimPath] = value

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

        @pickedWorldPos.setter
        def pickedWorldPos(self, value):
            self._batchedWriteValues[self._attributes.pickedWorldPos] = value

        def __getattr__(self, item: str):
            if item in self.LOCAL_PROPERTY_NAMES:
                return object.__getattribute__(self, item)
            else:
                return super().__getattr__(item)

        def __setattr__(self, item: str, new_value):
            if item in self.LOCAL_PROPERTY_NAMES:
                object.__setattr__(self, item, new_value)
            else:
                super().__setattr__(item, new_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 = OgnReadPickStateDatabase.ValuesForInputs(node, self.attributes.inputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_OUTPUT)
        self.outputs = OgnReadPickStateDatabase.ValuesForOutputs(node, self.attributes.outputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_STATE)
        self.state = OgnReadPickStateDatabase.ValuesForState(node, self.attributes.state, dynamic_attributes)
