import pytest
from pkgcore.resolver.choice_point import choice_point
from pkgcore.restrictions.boolean import AndRestriction, OrRestriction


class fake_package:

    def __init__(self, **kwds):
        for k, v in (
                ("bdepend", AndRestriction()),
                ("depend", AndRestriction()),
                ("rdepend", AndRestriction()),
                ("pdepend", AndRestriction()),
                ("idepend", AndRestriction()),
                ("slot", 0),
                ("key", None),
                ("marker", None)):
            setattr(self, k, kwds.get(k, v))

class TestChoicePoint:

    @staticmethod
    def gen_choice_point():
        return choice_point("asdf", (
            fake_package(marker=1, depend=OrRestriction(
                        "ordep1", "ordep2", "dependordep"),
                rdepend=AndRestriction(
                        OrRestriction("ordep1", "andordep2"),
                        "anddep1", "anddep2", "pkg1and"),
                pdepend=OrRestriction("prdep1", "or3")),
            fake_package(marker=2, depend=AndRestriction(
                        "anddep1", "anddep2"),
                rdepend=OrRestriction("or1", "or2"),
                pdepend=OrRestriction("prdep1", "or3"))))

    def test_depend_rdepend_stepping(self):
        c = self.gen_choice_point()
        assert c.depend == [["ordep1", "ordep2", "dependordep"]]
        assert sorted(c.rdepend) == sorted([['anddep1'], ['anddep2'], ['ordep1', 'andordep2'], ['pkg1and']])
        c.reduce_atoms("ordep1")
        assert c.depend == [['ordep2', 'dependordep']]
        assert sorted(c.rdepend) == sorted([['anddep1'], ['anddep2'], ['andordep2'], ['pkg1and']])
        c.reduce_atoms("pkg1and")
        c.reduce_atoms("or1")
        assert c.rdepend == [["or2"]]
        c.reduce_atoms("prdep1")
        assert c.depend == [['anddep1'], ['anddep2']]
        assert c.pdepend == [["or3"]]
        c.reduce_atoms("or3")
        with pytest.raises(IndexError):
            c.depend

    def test_current_pkg(self):
        c = self.gen_choice_point()
        assert c.current_pkg.marker == 1
        c.reduce_atoms("pkg1and")
        assert c.current_pkg.marker == 2

    def test_reduce(self):
        c = self.gen_choice_point()
        assert c.current_pkg.marker == 1
        assert not c.reduce_atoms("dependordep")
        assert not c.reduce_atoms("ordep2")
        assert c.reduce_atoms("ordep1")
        assert c.current_pkg.marker == 2
        c = self.gen_choice_point()
        assert c.reduce_atoms("anddep2")
        c = self.gen_choice_point()
        c.reduce_atoms("anddep1")
        with pytest.raises(IndexError):
            c.depend
        with pytest.raises(IndexError):
            c.rdepend
        with pytest.raises(IndexError):
            c.pdepend

    def test_nonzero(self):
        c = self.gen_choice_point()
        assert bool(c)
        assert c.current_pkg.marker == 1
        c.reduce_atoms("anddep1")
        assert not bool(c)
