import unittest
from modelverse_state.main import ModelverseState

from modelverse_state import status

class TestReadReverseDict(unittest.TestCase):
    def setUp(self):
        self.mvs = ModelverseState()

    def test_read_reverse_dict_no_exists(self):
        l, r = self.mvs.read_reverse_dict(-1, "abc")
        self.assertEquals(l, None)
        self.assertEquals(r, status.FAIL_RRDICT_UNKNOWN)

    def test_read_reverse_dict_not_found_node(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)

        # Passing data is not enforced, as the data will be interpreted if necessary
        l, r = self.mvs.read_reverse_dict(a, "abc")
        self.assertEquals(l, None)
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)

    def test_read_reverse_dict_not_found_nodevalue(self):
        a, r = self.mvs.create_nodevalue(1)
        self.assertEquals(r, status.SUCCESS)

        # Passing data is not enforced, as the data will be interpreted if necessary
        l, r = self.mvs.read_reverse_dict(a, "abc")
        self.assertEquals(l, None)
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)

    def test_read_reverse_dict_not_found_edge(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_edge(a, b)
        self.assertEquals(r, status.SUCCESS)

        # Passing data is not enforced, as the data will be interpreted if necessary
        l, r = self.mvs.read_reverse_dict(c, "abc")
        self.assertEquals(l, None)
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)

    def test_read_reverse_dict_no_primitive(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)

        # Passing data is not enforced, as the data will be interpreted if necessary
        l, r = self.mvs.read_reverse_dict(a, a)
        self.assertEquals(l, None)
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)

    def test_read_reverse_dict_node_simple(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_nodevalue("f")
        self.assertEquals(r, status.SUCCESS)
        d, r = self.mvs.create_edge(a, b)
        self.assertEquals(r, status.SUCCESS)
        e, r = self.mvs.create_edge(d, c)
        self.assertEquals(r, status.SUCCESS)

        l, r = self.mvs.read_reverse_dict(b, "f")
        self.assertEquals(r, status.SUCCESS)
        self.assertEquals(l, [a])

    def test_read_reverse_dict_no_match(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_nodevalue("g")
        self.assertEquals(r, status.SUCCESS)
        d, r = self.mvs.create_edge(a, b)
        self.assertEquals(r, status.SUCCESS)
        e, r = self.mvs.create_edge(d, c)
        self.assertEquals(r, status.SUCCESS)

        l, r = self.mvs.read_reverse_dict(b, "f")
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)
        self.assertEquals(l, None)

    def test_read_reverse_dict_node_multi(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_nodevalue("f")
        self.assertEquals(r, status.SUCCESS)
        d, r = self.mvs.create_edge(a, b)
        self.assertEquals(r, status.SUCCESS)
        e, r = self.mvs.create_edge(d, c)
        self.assertEquals(r, status.SUCCESS)

        g, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        h, r = self.mvs.create_nodevalue("k")
        self.assertEquals(r, status.SUCCESS)
        i, r = self.mvs.create_edge(a, g)
        self.assertEquals(r, status.SUCCESS)
        j, r = self.mvs.create_edge(i, h)
        self.assertEquals(r, status.SUCCESS)

        l, r = self.mvs.read_reverse_dict(b, "f")
        self.assertEquals(r, status.SUCCESS)
        self.assertEquals(l, [a])

        l, r = self.mvs.read_reverse_dict(g, "k")
        self.assertEquals(r, status.SUCCESS)
        self.assertEquals(l, [a])

        l, r = self.mvs.read_reverse_dict(a, "l")
        self.assertEquals(r, status.FAIL_RRDICT_NOT_FOUND)
        self.assertEquals(l, None)

    def test_read_reverse_dict_node_multi_ambiguous(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_nodevalue("f")
        self.assertEquals(r, status.SUCCESS)
        d, r = self.mvs.create_edge(b, a)
        self.assertEquals(r, status.SUCCESS)
        e, r = self.mvs.create_edge(d, c)
        self.assertEquals(r, status.SUCCESS)

        g, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        h, r = self.mvs.create_nodevalue("f")
        self.assertEquals(r, status.SUCCESS)
        i, r = self.mvs.create_edge(g, a)
        self.assertEquals(r, status.SUCCESS)
        j, r = self.mvs.create_edge(i, h)
        self.assertEquals(r, status.SUCCESS)

        l, r = self.mvs.read_reverse_dict(a, "f")
        self.assertEquals(r, status.SUCCESS)
        self.assertEquals(sorted(l), sorted([b, g]))

    def test_read_reverse_dict_node_uncertain(self):
        a, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        b, r = self.mvs.create_node()
        self.assertEquals(r, status.SUCCESS)
        c, r = self.mvs.create_nodevalue("f")
        self.assertEquals(r, status.SUCCESS)
        d, r = self.mvs.create_edge(a, b)
        self.assertEquals(r, status.SUCCESS)
        e, r = self.mvs.create_edge(d, c)
        self.assertEquals(r, status.SUCCESS)

        h, r = self.mvs.create_nodevalue("g")
        self.assertEquals(r, status.SUCCESS)
        i, r = self.mvs.create_edge(d, h)
        self.assertEquals(r, status.SUCCESS)

        l, r = self.mvs.read_reverse_dict(b, "f")
        self.assertEquals(r, status.FAIL_RRDICT_UNCERTAIN)
        self.assertEquals(l, None)
