"""OmniGraph deletion tests"""
import omni.graph.core as og
import omni.graph.core.tests as ogts
import omni.kit.commands
import omni.kit.test
import omni.usd


class TestOmniGraphDeletion(ogts.OmniGraphTestCase):
    # In these tests, we test various aspects of deleting things from OG

    async def test_omnigraph_usd_deletion(self):
        # In this test we set up 2 very similar looking nodes:
        # /new_node and /new_node_01.  We then delete /new_node
        # The idea is that this looks very similar to cases like
        # /parent/path/stuff/mynode where we delete /parent/path
        # In that case we want to delete mynode, but in our case
        # we do not want to delete /new_node_01 when /new_node is
        # deleted.
        keys = og.Controller.Keys
        (graph, [new_node, new_node_01], _, _) = og.Controller.edit(
            "/TestGraph",
            {
                keys.CREATE_NODES: [
                    ("new_node", "omni.graph.tutorials.Empty"),
                    ("new_node_01", "omni.graph.tutorials.Empty"),
                ]
            },
        )
        await og.Controller.evaluate()
        self.assertIsNotNone(new_node_01)
        self.assertTrue(new_node_01.is_valid())
        self.assertIsNotNone(new_node)
        self.assertTrue(new_node.is_valid())

        og.Controller.delete_node(new_node)

        new_node_01 = graph.get_node("/TestGraph/new_node_01")
        self.assertIsNotNone(new_node_01)
        self.assertTrue(new_node_01.is_valid())
        new_node = graph.get_node("/TestGraph/new_node")
        self.assertTrue(not new_node.is_valid())

        omni.kit.undo.undo()

        new_node_01 = graph.get_node("/TestGraph/new_node_01")
        self.assertIsNotNone(new_node_01)
        self.assertTrue(new_node_01.is_valid())
        new_node = graph.get_node("/TestGraph/new_node")
        self.assertIsNotNone(new_node)
        self.assertTrue(new_node.is_valid())

    # --------------------------------------------------------------------------------------------------------------
    async def test_fabric_dangling_connections(self):
        # In this test we create two nodes, connect them together.  The output of the first node drives the input
        # of the second node.  When we break the connection, we need to verify that the output of the second node
        # now takes its input from its own value, rather than the connected value (ie. the connection is actually
        # broken in the fabric).
        keys = og.Controller.Keys
        (graph, [node_a, node_b], _, _) = og.Controller.edit(
            "/TestGraph",
            {
                keys.CREATE_NODES: [
                    ("node_a", "omni.graph.tutorials.SimpleData"),
                    ("node_b", "omni.graph.tutorials.SimpleData"),
                ]
            },
        )
        await og.Controller.evaluate()

        node_a = graph.get_node("/TestGraph/node_a")
        self.assertIsNotNone(node_a)
        self.assertTrue(node_a.is_valid())
        node_b = graph.get_node("/TestGraph/node_b")
        self.assertIsNotNone(node_b)
        self.assertTrue(node_b.is_valid())

        upstream_attr = node_a.get_attribute("outputs:a_int")
        downstream_attr = node_b.get_attribute("inputs:a_int")

        og.Controller.connect(upstream_attr, downstream_attr)
        await og.Controller.evaluate()

        # This node "omni.graph.tutorials.SimpleData" add 1 to the input. The default value of a_int is 0, so the output
        # of the first node is 1.  When this is used as the input to the second node, we expect the value to be 2:
        value = og.Controller.get(node_b.get_attribute("outputs:a_int"))
        self.assertEqual(value, 2)

        og.Controller.disconnect(upstream_attr, downstream_attr)
        await og.Controller.evaluate()

        # Now that the connection is broken, the value should now be 1.  However, if it didn't actually break the
        # connection in the fabric, the graph would still "think" it's connected and output 2.
        value = og.Controller.get(node_b.get_attribute("outputs:a_int"))
        self.assertEqual(value, 1)
