"""
Implementation of the Python node accessing attributes through the bundle in which they are contained.
"""
import numpy as np
import omni.graph.core as og

# Types recognized by the integer filter
_INTEGER_TYPES = [og.BaseDataType.INT, og.BaseDataType.UINT, og.BaseDataType.INT64, og.BaseDataType.UINT64]


class OgnTutorialBundleDataPy:
    """Exercise the bundled data types through a Python OmniGraph node"""

    @staticmethod
    def compute(db) -> bool:
        """Implements the same algorithm as the C++ node OgnTutorialBundleData.cpp
        As Python is so much more flexible it doubles values on any attribute type that can handle it, unlike
        the C++ node which only operates on integer types
        """

        input_bundle = db.inputs.bundle
        output_bundle = db.outputs.bundle

        # This does a copy of the full bundle contents from the input bundle to the output bundle so that the
        # output data can be modified directly.
        output_bundle.bundle = input_bundle

        # The "attributes" member is a list that can be iterated. The members of the list do not contain real
        # og.Attribute objects, which must always exist, they are wrappers on og.AttributeData objects, which can
        # come and go at runtime.
        for bundled_attribute in output_bundle.attributes:

            attribute_type = bundled_attribute.type
            # Only integer types are recognized for this node's operation (doubling all integral values).
            # It does operate on tuples and arrays though so that part does not need to be set.
            # if attribute_type.base_type not in _INTEGER_TYPES:
            #     continue

            # This operation does the right thing on all compatible types, unlike the C++ equivalent where it
            # requires special handling for each variation of the data types it can handle.
            if attribute_type.base_type == og.BaseDataType.TOKEN:
                if attribute_type.array_depth > 0:
                    bundled_attribute.value = [f"{element}{element}" for element in bundled_attribute.value]
                else:
                    bundled_attribute.value = f"{bundled_attribute.value}{bundled_attribute.value}"
            elif attribute_type.role in [og.AttributeRole.TEXT, og.AttributeRole.PATH]:
                bundled_attribute.value = f"{bundled_attribute.value}{bundled_attribute.value}"
            else:
                try:
                    bundled_attribute.value = np.multiply(bundled_attribute.value, 2)
                except TypeError:
                    db.log_error(f"This node does not handle data of type {attribute_type.get_type_name()}")

        return True
