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

Makes an output array attribute from input values, in the order of the inputs. If 'arraySize' is less than the number of
input elements, the top 'arraySize' elements will be used. If 'arraySize' is greater than the number of input elements, the
last input element will be repeated to fill the remaining space.
"""

from typing import Any

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



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

    Class Members:
        node: Node being evaluated

    Attribute Value Properties:
        Inputs:
            inputs.arraySize
            inputs.arrayType
            inputs.input0
        Outputs:
            outputs.array

    Predefined Tokens:
        tokens.Auto
        tokens.Bool
        tokens.Double
        tokens.Float
        tokens.Half
        tokens.Int
        tokens.Int64
        tokens.Token
        tokens.UChar
        tokens.UInt
        tokens.UInt64
        tokens.Double_2
        tokens.Double_3
        tokens.Double_4
        tokens.Double_9
        tokens.Double_16
        tokens.Float_2
        tokens.Float_3
        tokens.Float_4
        tokens.Half_2
        tokens.Half_3
        tokens.Half_4
        tokens.Int_2
        tokens.Int_3
        tokens.Int_4
    """

    # 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:arraySize', 'int', 0, None, 'The size of the array to create', {ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.DEFAULT: '1'}, True, 1, False, ''),
        ('inputs:arrayType', 'token', 0, 'Array Type', "The type of the array ('auto' infers the type from the first connected and resolved input)", {ogn.MetadataKeys.LITERAL_ONLY: '1', ogn.MetadataKeys.ALLOWED_TOKENS: 'auto,bool[],double[],float[],half[],int[],int64[],token[],uchar[],uint[],uint64[],double[2][],double[3][],double[4][],matrixd[3][],matrixd[4][],float[2][],float[3][],float[4][],half[2][],half[3][],half[4][],int[2][],int[3][],int[4][]', ogn.MetadataKeys.ALLOWED_TOKENS_RAW: '{"Auto": "auto", "Bool": "bool[]", "Double": "double[]", "Float": "float[]", "Half": "half[]", "Int": "int[]", "Int64": "int64[]", "Token": "token[]", "UChar": "uchar[]", "UInt": "uint[]", "UInt64": "uint64[]", "Double_2": "double[2][]", "Double_3": "double[3][]", "Double_4": "double[4][]", "Double_9": "matrixd[3][]", "Double_16": "matrixd[4][]", "Float_2": "float[2][]", "Float_3": "float[3][]", "Float_4": "float[4][]", "Half_2": "half[2][]", "Half_3": "half[3][]", "Half_4": "half[4][]", "Int_2": "int[2][]", "Int_3": "int[3][]", "Int_4": "int[4][]"}', ogn.MetadataKeys.DEFAULT: '"auto"'}, True, "auto", False, ''),
        ('inputs:input0', 'any', 2, None, 'Input array element', {}, True, None, False, ''),
        ('outputs:array', 'any', 2, None, 'The array of copied values of inputs in the given order', {}, True, None, False, ''),
    ])

    class tokens:
        Auto = "auto"
        Bool = "bool[]"
        Double = "double[]"
        Float = "float[]"
        Half = "half[]"
        Int = "int[]"
        Int64 = "int64[]"
        Token = "token[]"
        UChar = "uchar[]"
        UInt = "uint[]"
        UInt64 = "uint64[]"
        Double_2 = "double[2][]"
        Double_3 = "double[3][]"
        Double_4 = "double[4][]"
        Double_9 = "matrixd[3][]"
        Double_16 = "matrixd[4][]"
        Float_2 = "float[2][]"
        Float_3 = "float[3][]"
        Float_4 = "float[4][]"
        Half_2 = "half[2][]"
        Half_3 = "half[3][]"
        Half_4 = "half[4][]"
        Int_2 = "int[2][]"
        Int_3 = "int[3][]"
        Int_4 = "int[4][]"

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

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

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

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

        @property
        def input0(self) -> og.RuntimeAttribute:
            """Get the runtime wrapper class for the attribute inputs.input0"""
            return og.RuntimeAttribute(self._attributes.input0.get_attribute_data(), self._context, True)

        @input0.setter
        def input0(self, value_to_set: Any):
            """Assign another attribute's value to outputs.input0"""
            if isinstance(value_to_set, og.RuntimeAttribute):
                self.input0.value = value_to_set.value
            else:
                self.input0.value = value_to_set

        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 array(self) -> og.RuntimeAttribute:
            """Get the runtime wrapper class for the attribute outputs.array"""
            return og.RuntimeAttribute(self._attributes.array.get_attribute_data(), self._context, False)

        @array.setter
        def array(self, value_to_set: Any):
            """Assign another attribute's value to outputs.array"""
            if isinstance(value_to_set, og.RuntimeAttribute):
                self.array.value = value_to_set.value
            else:
                self.array.value = value_to_set

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