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

Finds Prims on the stage which match the given criteria
"""

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 OgnFindPrimsDatabase(og.Database):
    """Helper class providing simplified access to data on nodes of type omni.graph.nodes.FindPrims

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.ignoreSystemPrims
            inputs.namePrefix
            inputs.pathPattern
            inputs.recursive
            inputs.requiredAttributes
            inputs.requiredRelationship
            inputs.requiredRelationshipTarget
            inputs.requiredTarget
            inputs.rootPrim
            inputs.rootPrimPath
            inputs.type
        Outputs:
            outputs.primPaths
            outputs.prims
        State:
            state.ignoreSystemPrims
            state.inputType
            state.namePrefix
            state.pathPattern
            state.recursive
            state.requiredAttributes
            state.requiredRelationship
            state.requiredRelationshipTarget
            state.requiredTarget
            state.rootPrim
            state.rootPrimPath
    """

    # 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:ignoreSystemPrims', 'bool', 0, None, "Ignore system prims such as omni graph nodes that shouldn't be considered during the import.", {ogn.MetadataKeys.DEFAULT: 'false'}, True, False, False, ''),
        ('inputs:namePrefix', 'token', 0, 'Prim Name Prefix', 'Only prims with a name starting with the given prefix will be returned.', {}, True, "", False, ''),
        ('inputs:pathPattern', 'token', 0, 'Prim Path Pattern', "A list of wildcard patterns used to match the prim paths\n\nSupported syntax of wildcard pattern:\n    '*' - match an arbitrary number of any characters\n    '?' - match any single character\n    '^' - (caret) is used to define a pattern that is to be excluded\n\nExample of wildcard patterns, input: ['/Cube0', '/Cube1', '/Box']\n    '*' - match any\n    '* ^/Box' - match any, but exclude '/Box'\n    '* ^/Cube*' - match any, but exclude '/Cube0' and '/Cube1'", {}, True, "", False, ''),
        ('inputs:recursive', 'bool', 0, None, 'False means only consider children of the root prim, True means all prims in the hierarchy', {}, True, False, False, ''),
        ('inputs:requiredAttributes', 'string', 0, 'Attribute Names', 'A space-separated list of attribute names that are required to be present on matched prims', {}, True, "", False, ''),
        ('inputs:requiredRelationship', 'token', 0, 'Relationship Name', 'The name of a relationship which must have a target specified by requiredRelationshipTarget or requiredTarget', {}, True, "", False, ''),
        ('inputs:requiredRelationshipTarget', 'path', 0, 'Relationship Prim Path', 'The path that must be a target of the requiredRelationship', {}, True, "", True, 'Use requiredTarget instead'),
        ('inputs:requiredTarget', 'target', 0, 'Relationship Prim', 'The target of the requiredRelationship', {}, True, [], False, ''),
        ('inputs:rootPrim', 'target', 0, 'Root Prim', 'Only children of the given prim will be considered. If rootPrim is specified, rootPrimPath will be ignored.', {}, True, [], False, ''),
        ('inputs:rootPrimPath', 'token', 0, 'Root Prim Path', 'Only children of the given prim will be considered. Empty will search the whole stage.', {}, True, "", True, 'Use rootPrim input attribute instead'),
        ('inputs:type', 'token', 0, 'Prim Type Pattern', "A list of wildcard patterns used to match the prim types that are to be imported\n\nSupported syntax of wildcard pattern:\n    '*' - match an arbitrary number of any characters\n    '?' - match any single character\n    '^' - (caret) is used to define a pattern that is to be excluded\n\nExample of wildcard patterns, input: ['Mesh', 'Cone', 'Cube']\n    '*' - match any\n    '* ^Mesh' - match any, but exclude 'Mesh'\n    '* ^Cone ^Cube' - match any, but exclude 'Cone' and 'Cube'", {ogn.MetadataKeys.DEFAULT: '"*"'}, True, "*", False, ''),
        ('outputs:primPaths', 'token[]', 0, None, 'A list of Prim paths as tokens which match the given type', {}, True, None, False, ''),
        ('outputs:prims', 'target', 0, None, 'A list of Prim paths which match the given type', {}, True, [], False, ''),
        ('state:ignoreSystemPrims', 'bool', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:inputType', 'token', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:namePrefix', 'token', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:pathPattern', 'token', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:recursive', 'bool', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:requiredAttributes', 'string', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:requiredRelationship', 'token', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:requiredRelationshipTarget', 'string', 0, None, 'last corresponding input seen', {}, True, None, False, ''),
        ('state:requiredTarget', 'target', 0, None, 'last corresponding input seen', {}, True, [], False, ''),
        ('state:rootPrim', 'target', 0, None, 'last corresponding input seen', {}, True, [], False, ''),
        ('state:rootPrimPath', 'token', 0, None, 'last corresponding input seen', {}, 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.requiredAttributes = og.AttributeRole.TEXT
        role_data.inputs.requiredRelationshipTarget = og.AttributeRole.PATH
        role_data.inputs.requiredTarget = og.AttributeRole.TARGET
        role_data.inputs.rootPrim = og.AttributeRole.TARGET
        role_data.outputs.prims = og.AttributeRole.TARGET
        role_data.state.requiredAttributes = og.AttributeRole.TEXT
        role_data.state.requiredRelationshipTarget = og.AttributeRole.TEXT
        role_data.state.requiredTarget = og.AttributeRole.TARGET
        role_data.state.rootPrim = og.AttributeRole.TARGET
        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 ignoreSystemPrims(self):
            data_view = og.AttributeValueHelper(self._attributes.ignoreSystemPrims)
            return data_view.get()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        @prims.setter
        def prims(self, value):
            data_view = og.AttributeValueHelper(self._attributes.prims)
            data_view.set(value)
            self.prims_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)
            self.requiredAttributes_size = None
            self.requiredRelationshipTarget_size = None
            self.requiredTarget_size = None
            self.rootPrim_size = None

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

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

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

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

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

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

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

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

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

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

        @property
        def requiredAttributes(self):
            data_view = og.AttributeValueHelper(self._attributes.requiredAttributes)
            self.requiredAttributes_size = data_view.get_array_size()
            return data_view.get()

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

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

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

        @property
        def requiredRelationshipTarget(self):
            data_view = og.AttributeValueHelper(self._attributes.requiredRelationshipTarget)
            self.requiredRelationshipTarget_size = data_view.get_array_size()
            return data_view.get()

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

        @property
        def requiredTarget(self):
            data_view = og.AttributeValueHelper(self._attributes.requiredTarget)
            self.requiredTarget_size = data_view.get_array_size()
            return data_view.get()

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

        @property
        def rootPrim(self):
            data_view = og.AttributeValueHelper(self._attributes.rootPrim)
            self.rootPrim_size = data_view.get_array_size()
            return data_view.get()

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

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

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

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