from collections import defaultdict

from pkgcore.ebuild.misc import sort_keywords
from pkgcore.restrictions import packages, values
from snakeoil.strings import pluralism

from .. import addons, results, sources
from . import GentooRepoCheck


class UnstableOnly(results.PackageResult, results.Info):
    """Package/keywords that are strictly unstable."""

    def __init__(self, versions, arches, **kwargs):
        super().__init__(**kwargs)
        self.versions = tuple(versions)
        self.arches = tuple(arches)

    @property
    def desc(self):
        es = pluralism(self.arches, plural='es')
        arches = ', '.join(self.arches)
        versions = ', '.join(self.versions)
        return f'for arch{es}: [ {arches} ], all versions are unstable: [ {versions} ]'


class UnstableOnlyCheck(GentooRepoCheck):
    """Scan for packages that have just unstable keywords."""

    _source = sources.PackageRepoSource
    required_addons = (addons.StableArchesAddon,)
    known_results = frozenset([UnstableOnly])

    def __init__(self, *args, stable_arches_addon=None):
        super().__init__(*args)
        arches = {x.strip().lstrip("~") for x in self.options.stable_arches}

        # stable, then unstable, then file
        self.arch_restricts = {}
        for arch in arches:
            self.arch_restricts[arch] = [
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch2((arch,))),
                packages.PackageRestriction(
                    "keywords", values.ContainmentMatch2((f"~{arch}",)))
            ]

    def feed(self, pkgset):
        # stable, then unstable, then file
        unstable_arches = defaultdict(list)
        for k, v in self.arch_restricts.items():
            stable = unstable = None
            for x in pkgset:
                if v[0].match(x):
                    stable = x
                    break
            if stable is not None:
                continue
            if unstable := tuple(x for x in pkgset if v[1].match(x)):
                unstable_arches[unstable].append(k)

        # collapse reports by available versions
        for pkgs in unstable_arches.keys():
            versions = (x.fullver for x in sorted(pkgs))
            yield UnstableOnly(versions, sort_keywords(unstable_arches[pkgs]), pkg=pkgs[0])
