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

Queries information about the type of a specified attribute in an input bundle
"""


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



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

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.attrName
            inputs.data
        Outputs:
            outputs.arrayDepth
            outputs.baseType
            outputs.componentCount
            outputs.fullType
            outputs.role
    """

    # 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:attrName', 'token', 0, 'Attribute To Query', 'The name of the attribute to be queried', {ogn.MetadataKeys.DEFAULT: '"input"'}, True, "input", False, ''),
        ('inputs:data', 'bundle', 0, 'Bundle To Examine', 'Bundle of attributes to examine', {}, True, None, False, ''),
        ('outputs:arrayDepth', 'int', 0, 'Attribute Array Depth', 'Zero for a single value, one for an array, two for an array of arrays.\nSet to -1 if the named attribute was not in the bundle.', {}, True, None, False, ''),
        ('outputs:baseType', 'int', 0, 'Attribute Base Type', 'An integer representing the type of the individual components.\nSet to -1 if the named attribute was not in the bundle.', {}, True, None, False, ''),
        ('outputs:componentCount', 'int', 0, 'Attribute Component Count', 'Number of components in each tuple, e.g. one for float, three for point3f, 16 for\nmatrix4d. Set to -1 if the named attribute was not in the bundle.', {}, True, None, False, ''),
        ('outputs:fullType', 'int', 0, 'Full Attribute Type', 'A single int representing the full type information.\nSet to -1 if the named attribute was not in the bundle.', {}, True, None, False, ''),
        ('outputs:role', 'int', 0, 'Attribute Role', 'An integer representing semantic meaning of the type, e.g. point3f vs. normal3f vs. vector3f vs. float3.\nSet to -1 if the named attribute was not in the bundle.', {}, True, None, False, ''),
    ])

    @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.data = og.AttributeRole.BUNDLE
        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.__bundles = og.BundleContainer(context, node, attributes, [], read_only=True, gpu_ptr_kinds={})
            self._batchedReadAttributes = []
            self._batchedReadValues = []

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

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

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

        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 arrayDepth(self):
            data_view = og.AttributeValueHelper(self._attributes.arrayDepth)
            return data_view.get()

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

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

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

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

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

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

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

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

        @role.setter
        def role(self, value):
            data_view = og.AttributeValueHelper(self._attributes.role)
            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 = OgnAttrTypeDatabase.ValuesForInputs(node, self.attributes.inputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_OUTPUT)
        self.outputs = OgnAttrTypeDatabase.ValuesForOutputs(node, self.attributes.outputs, dynamic_attributes)
        dynamic_attributes = self.dynamic_attribute_data(node, og.AttributePortType.ATTRIBUTE_PORT_TYPE_STATE)
        self.state = OgnAttrTypeDatabase.ValuesForState(node, self.attributes.state, dynamic_attributes)
