"""
Implementation of the Python node accessing all of the simple data types.
This class exercises access to the DataModel through the generated database class for all simple data types.
It implements the same algorithm as the C++ node OgnTutorialSimpleData.cpp
"""
import omni.graph.tools.ogn as ogn


class OgnTutorialSimpleDataPy:
    """Exercise the simple data types through a Python OmniGraph node"""

    @staticmethod
    def compute(db) -> bool:
        """Perform a trivial computation on all of the simple data types to make testing easy"""
        # Inside the database the contained object "inputs" holds the data references for all input attributes and the
        # contained object "outputs" holds the data references for all output attributes.

        # Each of the attribute accessors are named for the name of the attribute, with the ":" replaced by "_".
        # The colon is used in USD as a convention for creating namespaces so it's safe to replace it without
        # modifying the meaning. The "inputs:" and "outputs:" prefixes in the generated attributes are matched
        # by the container names.

        # For example attribute "inputs:translate:x" would be accessible as "db.inputs.translate_x" and attribute
        # "outputs:matrix" would be accessible as "db.outputs.matrix".

        # The "compute" of this method modifies each attribute in a subtle way so that a test can be written
        # to verify the operation of the node. See the .ogn file for a description of tests.
        db.outputs.a_bool = not db.inputs.a_bool
        db.outputs.a_half = 1.0 + db.inputs.a_half
        db.outputs.a_int = 1 + db.inputs.a_int
        db.outputs.a_int64 = 1 + db.inputs.a_int64
        db.outputs.a_double = 1.0 + db.inputs.a_double
        db.outputs.a_float = 1.0 + db.inputs.a_float
        db.outputs.a_uchar = 1 + db.inputs.a_uchar
        db.outputs.a_uint = 1 + db.inputs.a_uint
        db.outputs.a_uint64 = 1 + db.inputs.a_uint64
        db.outputs.a_string = db.inputs.a_string.replace("hello", "world")
        db.outputs.a_objectId = 1 + db.inputs.a_objectId

        # The token interface is made available in the database as well, for convenience.
        # By calling "db.token" you can look up the token ID of a given string.
        if db.inputs.a_token == "helloToken":
            db.outputs.a_token = "worldToken"

        # Path just gets a new child named "Child".
        # In the implementation the string is manipulated directly, as it does not care if the SdfPath is valid or
        # not. If you want to manipulate it using the pxr.Sdf.Path API this is how you could do it:
        #
        #     from pxr import Sdf
        #     input_path Sdf.Path(db.inputs.a_path)
        #     if input_path.IsValid():
        #         db.outputs.a_path() = input_path.AppendChild("/Child").GetString();
        #
        db.outputs.a_path = db.inputs.a_path + "/Child"

        # To access the metadata you have to go out to the ABI, though the hardcoded metadata tags are in the
        # OmniGraph Python namespace
        assert db.node.get_attribute("inputs:a_bool").get_metadata(ogn.MetadataKeys.UI_NAME) == "Simple Boolean Input"

        # You can also use the database interface to get the same data
        db.outputs.a_nodeTypeUiName = db.get_metadata(ogn.MetadataKeys.UI_NAME)
        db.outputs.a_a_boolUiName = db.get_metadata(ogn.MetadataKeys.UI_NAME, db.attributes.inputs.a_bool)

        return True
