"""Basic tests of the metadata bindings found in OmniGraphBindingsPython.cpp"""
import omni.graph.core as og
import omni.graph.core.tests as ogts
import omni.graph.tools.ogn as ogn


# ======================================================================
class TestOmniGraphMetadata(ogts.OmniGraphTestCase):
    """Encapsulate simple tests that exercise metadata access"""

    # ----------------------------------------------------------------------
    def __node_type_metadata_test(self, node_type: og.NodeType):
        """Test a node type object for metadata access"""
        original_count = node_type.get_metadata_count()

        key = "_node_type_metadata"
        value = "_test_value"
        node_type.set_metadata(key, value)
        # The new metadata key should now have the new value
        self.assertEqual(value, node_type.get_metadata(key))

        new_metadata = node_type.get_all_metadata()
        # The new key/value pair should now be part of the entire metadata listt
        self.assertTrue(key in new_metadata)
        self.assertEqual(value, new_metadata[key])
        # Since a unique key was chosen there should be one extra metadata value
        self.assertEqual(original_count + 1, node_type.get_metadata_count())

        # Setting a value to None should remove the metadata from the node type.
        # Do this last so that the test can run multiple times successfully.
        node_type.set_metadata(key, None)
        self.assertEqual(original_count, node_type.get_metadata_count())

        # Test silent success of trying to set the metadata to illegal data
        node_type.set_metadata(None, value)

        # Verify the hardcoded metadata type names
        self.assertTrue(ogn.MetadataKeys.UI_NAME in new_metadata)
        self.assertTrue(ogn.MetadataKeys.TAGS in new_metadata)
        self.assertEqual("Tutorial Node: Tuple Attributes", new_metadata[ogn.MetadataKeys.UI_NAME])
        self.assertEqual("tuple,tutorial,internal", new_metadata[ogn.MetadataKeys.TAGS])

    # ----------------------------------------------------------------------
    async def test_node_type_metadata(self):
        """Test metadata features in the NodeType class"""
        # The TupleData tutorial node happens to have special metadata types defined
        node_type = og.get_node_type("omni.tutorials.TupleData")
        self.assertIsNotNone(node_type, "Empty node type to be used for test was not registered")
        self.__node_type_metadata_test(node_type)

    # ----------------------------------------------------------------------
    async def test_node_metadata(self):
        """Test metadata access through the node class"""
        # The TupleData tutorial node happens to have special metadata types defined
        (_, [test_node], _, _) = og.Controller.edit(
            "/TestGraph",
            {
                og.Controller.Keys.CREATE_NODES: ("TupleNode", "omni.tutorials.TupleData"),
            },
        )
        await og.Controller.evaluate()
        self.__node_type_metadata_test(test_node.get_node_type())

    # ----------------------------------------------------------------------
    async def test_attribute_metadata(self):
        """Test metadata features in the NodeType class"""
        # Any node type will do for metadata tests so use a simple one
        (_, [test_node], _, _) = og.Controller.edit(
            "/TestGraph",
            {
                og.Controller.Keys.CREATE_NODES: ("SimpleNode", "omni.graph.tutorials.SimpleData"),
            },
        )
        await og.Controller.evaluate()
        self.assertIsNotNone(test_node, "Simple data node type to be used for test was not registered")

        test_attribute = test_node.get_attribute("inputs:a_bool")
        self.assertIsNotNone(test_attribute, "Boolean input on simple data node type not found")

        original_count = test_attribute.get_metadata_count()

        key = "_test_attribute_metadata"
        value = "_test_value"
        test_attribute.set_metadata(key, value)
        # The new metadata key should now have the new value
        self.assertEqual(value, test_attribute.get_metadata(key))

        new_metadata = test_attribute.get_all_metadata()
        # The new key/value pair should now be part of the entire metadata listt
        self.assertTrue(key in new_metadata)
        self.assertEqual(value, new_metadata[key])
        # Since a unique key was chosen there should be one extra metadata value
        self.assertEqual(original_count + 1, test_attribute.get_metadata_count())

        # Setting a value to None should remove the metadata from the node type.
        # Do this last so that the test can run multiple times successfully.
        test_attribute.set_metadata(key, None)
        self.assertEqual(original_count, test_attribute.get_metadata_count())

        # Test silent success of trying to set the metadata to illegal data
        test_attribute.set_metadata(None, value)

        # ObjectId types get special metadata hardcoded
        for attribute_name in ["inputs:a_objectId", "outputs:a_objectId"]:
            object_id_attribute = test_node.get_attribute(attribute_name)
            self.assertIsNotNone(object_id_attribute, f"ObjectId {attribute_name} on simple data node type not found")
            object_id_metadata = object_id_attribute.get_all_metadata()
            self.assertTrue(ogn.MetadataKeys.OBJECT_ID in object_id_metadata)

        # Check on the constant attribute
        constant_attribute = test_node.get_attribute("inputs:a_constant_input")
        self.assertEqual("1", constant_attribute.get_metadata(ogn.MetadataKeys.OUTPUT_ONLY))
