class TestBagRequirementDiscover(unittest.TestCase):
    def setUp(self):
        self.connected_bag = Bag()
        self.connected_bag.silent = True
        repo = self.connected_bag
        repo.collection.delete_many({"TEST": ""})
        self.dep_1 = {"NAME": "DEP-1", "VERSION": "0.1.0", "TEST": ""}
        self.dep_2 = {
            "NAME":
            "DEP-2",
            "VERSION":
            "0.1.0",
            "TEST":
            "",
            "DEPENDENCIES": [{
                "NAME": "DEP-2-1",
                "VERSION": "1.1.1"
            }, {
                "NAME": "DEP-2-2",
                "VERSION": "1.2.3"
            }]
        }
        repo.charge(None, self.dep_1)
        repo.charge(None, {"NAME": "DEP-2-1", "VERSION": "1.1.1", "TEST": ""})
        repo.charge(None, {"NAME": "DEP-2-2", "VERSION": "1.2.3", "TEST": ""})
        repo.charge(None, self.dep_2)
        repo.charge(
            None, {
                "NAME":
                "P1",
                "VERSION":
                "1.0.0",
                "TEST":
                "",
                "DEPENDENCIES": [{
                    "NAME": "DEP-1",
                    "VERSION": "0.1.0"
                }, {
                    "NAME": "DEP-2",
                    "VERSION": "0.1.0"
                }]
            })

        repo.charge(
            None, {
                "NAME":
                "P0",
                "VERSION":
                "1.0.0",
                "TEST":
                "",
                "DEPENDENCIES": [{
                    "NAME": "DEP-1",
                    "VERSION": "0.1.0"
                }, {
                    "NAME": "DEP-2-1",
                    "VERSION": "1.1.1",
                    "TEST": ""
                }]
            })

        self.connected_bag.silent = False

    def tearDown(self):
        self.connected_bag.collection.delete_many({"TEST": ""})

    def test_bag_query_for_direct_project_dependencies(self):
        """
    Check the bag can discover direct dependencies for a given requirement
    """
        requirements = self.connected_bag.requirements_for(
            dep.Requirement({
                "NAME": "P1",
                "VERSION": "1.0.0"
            }))

        self.assertEqual(len(requirements), 2)
        self.assertTrue(dep.Requirement(self.dep_1) in requirements,
                        msg=str(dep.Requirement(self.dep_1)) + "\nRESULTS: " +
                        str(requirements))
        self.assertTrue(dep.Requirement(self.dep_2) in requirements,
                        msg=str(dep.Requirement(self.dep_2)) + "\nRESULTS: " +
                        str(requirements))

    def test_bag_query_for_direct_project_dependencies_only_direct_dep(self):
        """
    Check the bag can discover direct dependencies for a given requirement
    """
        requirements, gr = self.connected_bag.requirements_discover(
            dep.Requirement({
                "NAME": "P0",
                "VERSION": "1.0.0"
            }))
        self.assertEqual(
            len(requirements),
            gr.number_of_nodes(),
            msg=
            'number of dependency graph node do not match detected requirements number.'
        )
        self.assertEqual(len(requirements),
                         3,
                         msg='found requirements: ' + str(requirements))
        self.assertTrue(dep.Requirement(self.dep_1) in requirements,
                        msg=str(dep.Requirement(self.dep_1)) + "\nRESULTS: " +
                        str(requirements))

    def test_bag_query_for_project_dependencies(self):

        requirements, gr = self.connected_bag.requirements_discover(
            dep.Requirement({
                "NAME": "P1",
                "VERSION": "1.0.0"
            }))
        self.assertEqual(
            len(requirements),
            gr.number_of_nodes(),
            msg=
            'number of dependency graph node do not match detected requirements number.'
        )
        self.assertEqual(len(requirements),
                         5,
                         msg="discovered requirements: " + str(requirements))
        self.assertTrue(dep.Requirement(self.dep_1) in requirements)
        self.assertTrue(dep.Requirement(self.dep_2) in requirements)

        dep_2_1 = [r for r in requirements if r.NAME == "DEP-2-1"][0]
        self.assertEqual(dep_2_1.parent, dep.Requirement(self.dep_2))

    def test_bag_query_for_multiple_dependencies(self):
        """
    Check the bag can discover the dependencies graph for a list of projects.
    This is the case of building the graph of dependencies of a project
    while it is still not mantained by pony. Need this to find out the dependency graph given the
    set of dependencies listed into the json metainformations fils.
    """
        requirements, gr = self.connected_bag.requirements_discover([
            dep.Requirement({
                "NAME": "P0",
                "VERSION": "1.0.0"
            }),
            dep.Requirement({"NAME": "DEP-2"})
        ])

        self.assertEqual(
            len(requirements),
            gr.number_of_nodes(),
            msg=
            'number of dependency graph node do not match detected requirements number.\n'
            + str(requirements) + '\nvs\n' + str(gr))
        self.assertEqual(len(requirements),
                         5,
                         msg='found requirements: ' + str(requirements))
        self.assertTrue(dep.Requirement(self.dep_1) in requirements,
                        msg=str(dep.Requirement(self.dep_1)) + "\nRESULTS: " +
                        str(requirements))

    def test_bag_query_for_project_cyrcular_dependency(self):
        """
    Checks the bag can deal, *using simple policy* with circular dependencies. Basically it do not loop infinitelly at least.
    """

        self.dep_circular = {
            "NAME": "DEP_CIR",
            "VERSION": "0.0.3",
            "TEST": "",
            "DEPENDENCIES": [{
                "NAME": "DEP-2",
                "VERSION": "0.1.0"
            }]
        }

        self.prj = {
            "NAME":
            "P",
            "VERSION":
            "0.0.3",
            "TEST":
            "",
            "DEPENDENCIES": [{
                "NAME": "P1",
                "VERSION": "1.0.0"
            }, {
                "NAME": "DEP_CIR",
                "VERSION": "0.0.3"
            }]
        }

        self.connected_bag.charge(None, self.dep_circular)
        self.connected_bag.charge(None, self.prj)

        requirements, gr = self.connected_bag.requirements_discover(
            dep.Requirement({
                "NAME": "P",
                "VERSION": "0.0.3"
            }))
        self.assertEqual(len(requirements),
                         7,
                         msg="discovered requirements: " + str(requirements))

        graph = self.connected_bag.requirements_graph(
            dep.Requirement({
                "NAME": "P",
                "VERSION": "0.0.3"
            }))
        print("check this")
        print(bag.to_dot_string(graph))