import pytest
from pkgcore.ebuild.atom import atom
from pkgcore.repository.util import SimpleTree
from pkgcore.scripts import pmerge
from pkgcore.test.misc import FakePkg, FakeRepo
from pkgcore.util.parserestrict import parse_match


# TODO: make repo objs into configurable fixtures
class TestTargetParsing:
    def test_base_targets(self):
        repo = SimpleTree({"spork": {"foon": ("1", "1.0.1", "2")}})
        installed_repos = SimpleTree({"foo": {"bar": ("1",)}})
        for cat in ("", "spork/"):
            a = pmerge.parse_target(parse_match(f"={cat}foon-1"), repo, installed_repos)
            assert len(a) == 1
            assert a[0].key == "spork/foon"
            assert [x.fullver for x in repo.itermatch(a[0])] == ["1"]
            a = pmerge.parse_target(parse_match(f"{cat}foon"), repo, installed_repos)
            assert len(a) == 1
            assert a[0].key == "spork/foon"
            assert sorted(x.fullver for x in repo.itermatch(a[0])) == sorted(
                ["1", "1.0.1", "2"]
            )

    def test_no_matches(self):
        repo = SimpleTree({"spork": {"foon": ("1",)}, "spork2": {"foon": ("2",)}})
        installed_repos = SimpleTree({"foo": {"bar": ("1",)}})
        with pytest.raises(pmerge.NoMatches):
            pmerge.parse_target(parse_match("foo"), repo, installed_repos)

    def test_ambiguous(self):
        repo = SimpleTree({"spork": {"foon": ("1",)}, "spork2": {"foon": ("2",)}})
        installed_repos = SimpleTree({"foo": {"bar": ("1",)}})
        with pytest.raises(pmerge.AmbiguousQuery):
            pmerge.parse_target(parse_match("foon"), repo, installed_repos)

    def test_globbing(self):
        repo = SimpleTree({"spork": {"foon": ("1",)}, "spork2": {"foon": ("2",)}})
        installed_repos = SimpleTree({"foo": {"bar": ("1",)}})
        a = pmerge.parse_target(parse_match("*/foon"), repo, installed_repos)
        assert len(a) == 2

    def test_collision_repo(self):
        # test pkg name collision between real and virtual pkgs in a repo, but not installed
        # repos, the real pkg will be selected over the virtual
        installed_repos = SimpleTree({"foo": {"baz": ("1",)}})
        repo = SimpleTree({"foo": {"bar": ("1",)}, "virtual": {"bar": ("1",)}})
        a = pmerge.parse_target(parse_match("bar"), repo, installed_repos)
        assert len(a) == 1
        assert a[0].key == "foo/bar"
        assert [x.key for x in repo.match(a[0])] == ["foo/bar"]

    def test_collision_livefs(self):
        # test pkg name collision between real and virtual pkgs on livefs
        # repos, the real pkg will be selected over the virtual
        installed_repos = SimpleTree(
            {"foo": {"bar": ("1",)}, "virtual": {"bar": ("0",)}}
        )
        repo = SimpleTree({"foo": {"bar": ("1",)}, "virtual": {"bar": ("1",)}})
        a = pmerge.parse_target(parse_match("bar"), repo, installed_repos)
        assert len(a) == 1
        assert a[0].key == "foo/bar"
        assert [x.key for x in repo.match(a[0])] == ["foo/bar"]

    def test_collision_slotted(self):
        pkgs = [
            FakePkg("foo/bar-1.0.1", slot="0"),
            FakePkg("foo/bar-2.0.2", slot="2"),
            FakePkg("foon/bar-3.4.5", slot="0"),
        ]
        installed_pkgs = [
            FakePkg("foo/bar-1.0.0", slot="0"),
            FakePkg("foo/bar-2.0.1", slot="2"),
        ]
        installed_repos = FakeRepo(pkgs=installed_pkgs)
        repo = FakeRepo(pkgs=pkgs)
        a = pmerge.parse_target(parse_match("bar:0"), repo, installed_repos)
        assert len(a) == 1
        assert a[0].key == "foo/bar"
        assert a[0].match(atom("foo/bar:0"))
        assert not a[0].match(atom("foo/bar:2"))
