       0   invalid
  #   7li~?Jrţ/ ?     7#!/usr/bin/python

"""
TODO:
 * repository descriptions in kickstart format for non default repos
"""

import yum
from optparse import OptionParser
import sys

__stateprefixes = {
    None : '# ',
    "mandatory" : ".",
    "default" : "@",
    "all" : "*"
    }

def state2str(o):
    if isinstance(o, Group):
        o = o.state
    return __stateprefixes[o]

class Group:
    """Additional information about a comps group"""
    def __init__(self, compsgroup, yum, state=None):
        self.id = compsgroup.groupid
        self.state = None
        self.compsgroup = compsgroup
        self.yum = yum

        self.packages = {}
        for n in (None, "mandatory", "default", "all"):
            self.packages[n] = {}
            for s in ("add", "exclude", "exclude_missing", "optional"):
                self.packages[n][s] = set()

    @property
    def add(self):
        """Packages that this group adds to the install"""
        return self.packages[self.state]["add"]

    @property
    def exclude(self):
        """Packages excludes from this group to match the pkg list"""
        return self.packages[self.state]["exclude"]

    @property
    def excludeMissing(self):
        """Excludes that don't have a matching pgk in the repository"""
        return self.packages[self.state]["exclude_missing"]

    @property
    def optional(self):
        """Packages in this group that are not added in the current state"""
        return self.packages[self.state]["optional"]

    @property
    def addons(self):
        """Optional packages that are not added by the group in the given state but nevertheless need to be installed"""
        return self.packages[self.state]["addons"]

    def _buildSets(self, leafpkgs, allpkgs):
        # handle conditionals
        self.conditionals = set()
        for name, dep in self.compsgroup.conditional_packages.iteritems():
            if dep in allpkgs:
                self.conditionals.add(name)

        pkgs = self.conditionals.copy()
        for name, additionalpkgs in (
            ("mandatory", self.compsgroup.mandatory_packages),
            ("default", self.compsgroup.default_packages),
            ("all", self.compsgroup.optional_packages)):
            pkgs.update(additionalpkgs)
            self.__checkGroup(name, pkgs, leafpkgs, allpkgs)

        self.__checkGroup(None, set(), leafpkgs, allpkgs)
        for name, d in self.packages.iteritems():
            d["others"] = pkgs - d["add"] - d["exclude"]
            d["addons"] = d["others"] & leafpkgs

    def __checkGroup(self, name, pkgs, leafpkgs, allpkgs):
        self.packages[name]["add"] = leafpkgs & pkgs
        self.packages[name]["exclude"] = pkgs - allpkgs
        self.packages[name]["exclude_missing"] = set(
            pkg for pkg in self.packages[name]["exclude"] if not self.yum.pkgSack.searchNames([pkg]))
        return

    def _autodetectState(self, allowexcludes, allowed=("default",), sharedpkgs=None):
        """Set state of the group according to the installed packages"""
        win = None
        state = self.state
        for name, d in self.packages.iteritems():
            if name not in allowed and name is not None:
                continue
            if not allowexcludes and d["exclude"]:
                continue
            newshared = set()
            if sharedpkgs:
                for pkg in d["add"]:
                    if pkg in sharedpkgs and len(sharedpkgs[pkg]) > 1:
                        newshared.add(pkg)
            newwin = len(d["add"]) - len(d["exclude"]) - len(newshared) - 1
            if win is None or newwin > win:
                state = name
                win = newwin

        if win <= 0:
            state = None
        # reflect changes in sharedpkgs
        if state != self.state and sharedpkgs is not None:
            for pkg in self.packages[self.state]["add"] - self.packages[state]["add"]:
                if pkg in sharedpkgs:
                    sharedpkgs[pkg].discard(self)
            for pkg in self.package