# Copyright 2007-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import time

from portage import os
from portage.versions import catpkgsplit, catsplit, pkgcmp, best
from portage.dep import Atom
from portage.localization import _
from portage._sets.base import PackageSet
from portage._sets import SetConfigError, get_boolean
import portage

__all__ = ["CategorySet", "DowngradeSet",
	"EverythingSet", "OwnerSet", "VariableSet"]

class EverythingSet(PackageSet):
	_operations = ["merge"]
	description = "Package set which contains SLOT " + \
		"atoms to match all installed packages"
	_filter = None

	def __init__(self, vdbapi, **kwargs):
		super(EverythingSet, self).__init__()
		self._db = vdbapi

	def load(self):
		myatoms = []
		db_keys = ["SLOT"]
		aux_get = self._db.aux_get
		cp_list = self._db.cp_list

		for cp in self._db.cp_all():
			cpv_list = cp_list(cp)

			if len(cpv_list) > 1:
				for cpv in cpv_list:
					slot, = aux_get(cpv, db_keys)
					atom = Atom("%s:%s" % (cp, slot))
					if self._filter:
						if self._filter(atom):
							myatoms.append(atom)
					else:
						myatoms.append(atom)

			else:
				atom = Atom(cp)
				if self._filter:
					if self._filter(atom):
						myatoms.append(atom)
				else:
					myatoms.append(atom)

		self._setAtoms(myatoms)
	
	def singleBuilder(self, options, settings, trees):
		return EverythingSet(trees["vartree"].dbapi)
	singleBuilder = classmethod(singleBuilder)

class OwnerSet(PackageSet):

	_operations = ["merge", "unmerge"]

	description = "Package set which contains all packages " + \
		"that own one or more files."

	def __init__(self, vardb=None, exclude_files=None, files=None):
		super(OwnerSet, self).__init__()
		self._db = vardb
		self._exclude_files = exclude_files
		self._files = files

	def mapPathsToAtoms(self, paths, exclude_paths=None):
		"""
		All paths must have $EROOT stripped from the left side.
		"""
		rValue = set()
		vardb = self._db
		aux_get = vardb.aux_get
		aux_keys = ["SLOT"]
		if exclude_paths is None:
			for link, p in vardb._owners.iter_owners(paths):
				cat, pn = catpkgsplit(link.mycpv)[:2]
				slot, = aux_get(link.mycpv, aux_keys)
				rValue.add("%s/%s:%s" % (cat, pn, slot))
		else:
			all_paths = set()
			all_paths.update(paths)
			all_paths.update(exclude_paths)
			exclude_atoms = set()
			for link, p in vardb._owners.iter_owners(all_paths):
				cat, pn = catpkgsplit(link.mycpv)[:2]
				slot, = aux_get(link.mycpv, aux_keys)
				atom = "%s/%s:%s" % (cat, pn, slot)
				rValue.add(atom)
				if p in exclude_paths:
					exclude_atoms.add(atom)
			rValue.difference_update(exclude_atoms)

		return rValue

	def load(self):
		self._setAtoms(self.mapPathsToAtoms(self._files,
			exclude_paths=self._exclude_files))

	def singleBuilder(cls, options, settings, trees):
		if not "files" in options:
			raise SetConfigError(_("no files given"))

		exclude_files = options.get("exclude-files")
		if exclude_files is not None:
			exclude_files = frozenset(portage.util.shlex_split(exclude_files))
		return cls(vardb=trees["vartree"].dbapi, exclude_files=exclude_files,
			files=frozenset(portage.util.shlex_split(options["files"])))

	singleBuilder = classmethod(singleBuilder)

class VariableSet(EverythingSet):

	_operations = ["merge", "unmerge"]

	description = "Package set which contains all packages " + \
		"that match specified values of a specified variable."

	def __init__(self, vardb, metadatadb=None, variable=None, includes=None, excludes=None):
		super(VariableSet, self).__init__(vardb)
		self._metadatadb = metadatadb
		self._variable = variable
		self._includes = includes
		self._excludes = excludes

	def _filter(self, atom):
		ebuild = best(self._metadatadb.match(atom))
		if not ebuild:
			return False
		values, = self._metadatadb.aux_get(ebuild, [self._variable])
		values = values.split()
		if self._includes and not self._includes.intersection(values):
			return False
		if self._excludes and self._excludes.intersection(values):
			return False
		return True

	def singleBuilder(cls, options, settings, trees):

		variable = options.get("variable")
		if variable is None:
			raise SetConfigError(_("missing required attribute: 'variable'"))

		includes = options.get("includes", "")
		excludes = options.get("excludes", "")

		if not (includes or excludes):
			raise SetConfigError(_("no includes or excludes given"))
		
		metadatadb = options.get("metadata-source", "vartree")
		if not metadatadb in trees:
			raise SetConfigError(_("invalid value '%s' for option metadata-source") % metadatadb)

		return cls(trees["vartree"].dbapi,
			metadatadb=trees[metadatadb].dbapi,
			excludes=frozenset(excludes.split()),
			includes=frozenset(includes.split()),
			variable=variable)

	singleBuilder = classmethod(singleBuilder)

class DowngradeSet(PackageSet):

	_operations = ["merge", "unmerge"]

	description = "Package set which contains all packages " + \
		"for which the highest visible ebuild version is lower than " + \
		"the currently installed version."

	def __init__(self, portdb=None, vardb=None):
		super(DowngradeSet, self).__init__()
		self._portdb = portdb
		self._vardb = vardb

	def load(self):
		atoms = []
		xmatch = self._portdb.xmatch
		xmatch_level = "bestmatch-visible"
		cp_list = self._vardb.cp_list
		aux_get = self._vardb.aux_get
		aux_keys = ["SLOT"]
		for cp in self._vardb.cp_all():
			for cpv in cp_list(cp):
				slot, = aux_get(cpv, aux_keys)
				slot_atom = "%s:%s" % (cp, slot)
				ebuild = xmatch(xmatch_level, slot_atom)
				if not ebuild:
					continue
				ebuild_split = catpkgsplit(ebuild)[1:]
				installed_split = catpkgsplit(cpv)[1:]
				if pkgcmp(installed_split, ebuild_split) > 0:
					atoms.append(slot_atom)

		self._setAtoms(atoms)

	def singleBuilder(cls, options, settings, trees):
		return cls(portdb=trees["porttree"].dbapi,
			vardb=trees["vartree"].dbapi)

	singleBuilder = classmethod(singleBuilder)

class UnavailableSet(EverythingSet):

	_operations = ["unmerge"]

	description = "Package set which contains all installed " + \
		"packages for which there are no visible ebuilds " + \
		"corresponding to the same $CATEGORY/$PN:$SLOT."

	def __init__(self, vardb, metadatadb=None):
		super(UnavailableSet, self).__init__(vardb)
		self._metadatadb = metadatadb

	def _filter(self, atom):
		return not self._metadatadb.match(atom)

	def singleBuilder(cls, options, settings, trees):

		metadatadb = options.get("metadata-source", "porttree")
		if not metadatadb in trees:
			raise SetConfigError(_("invalid value '%s' for option "
				"metadata-source") % (metadatadb,))

		return cls(trees["vartree"].dbapi,
			metadatadb=trees[metadatadb].dbapi)

	singleBuilder = classmethod(singleBuilder)

class UnavailableBinaries(EverythingSet):

	_operations = ('merge', 'unmerge',)

	description = "Package set which contains all installed " + \
		"packages for which corresponding binary packages " + \
		"are not available."

	def __init__(self, vardb, metadatadb=None):
		super(UnavailableBinaries, self).__init__(vardb)
		self._metadatadb = metadatadb

	def _filter(self, atom):
		inst_pkg = self._db.match(atom)
		if not inst_pkg:
			return False
		inst_cpv = inst_pkg[0]
		return not self._metadatadb.cpv_exists(inst_cpv)

	def singleBuilder(cls, options, settings, trees):

		metadatadb = options.get("metadata-source", "bintree")
		if not metadatadb in trees:
			raise SetConfigError(_("invalid value '%s' for option "
				"metadata-source") % (metadatadb,))

		return cls(trees["vartree"].dbapi,
			metadatadb=trees[metadatadb].dbapi)

	singleBuilder = classmethod(singleBuilder)

class CategorySet(PackageSet):
	_operations = ["merge", "unmerge"]
	
	def __init__(self, category, dbapi, only_visible=True):
		super(CategorySet, self).__init__()
		self._db = dbapi
		self._category = category
		self._check = only_visible
		if only_visible:
			s="visible"
		else:
			s="all"
		self.description = "Package set containing %s packages of category %s" % (s, self._category)
			
	def load(self):
		myatoms = []
		for cp in self._db.cp_all():
			if catsplit(cp)[0] == self._category:
				if (not self._check) or len(self._db.match(cp)) > 0:
					myatoms.append(cp)
		self._setAtoms(myatoms)
	
	def _builderGetRepository(cls, options, repositories):
		repository = options.get("repository", "porttree")
		if not repository in repositories:
			raise SetConfigError(_("invalid repository class '%s'") % repository)
		return repository
	_builderGetRepository = classmethod(_builderGetRepository)

	def _builderGetVisible(cls, options):
		return get_boolean(options, "only_visible", True)
	_builderGetVisible = classmethod(_builderGetVisible)
		
	def singleBuilder(cls, options, settings, trees):
		if not "category" in options:
			raise SetConfigError(_("no category given"))

		category = options["category"]
		if not category in settings.categories:
			raise SetConfigError(_("invalid category name '%s'") % category)

		repository = cls._builderGetRepository(options, trees.keys())
		visible = cls._builderGetVisible(options)
		
		return CategorySet(category, dbapi=trees[repository].dbapi, only_visible=visible)
	singleBuilder = classmethod(singleBuilder)

	def multiBuilder(cls, options, settings, trees):
		rValue = {}
	
		if "categories" in options:
			categories = options["categories"].split()
			invalid = set(categories).difference(settings.categories)
			if invalid:
				raise SetConfigError(_("invalid categories: %s") % ", ".join(list(invalid)))
		else:
			categories = settings.categories
	
		repository = cls._builderGetRepository(options, trees.keys())
		visible = cls._builderGetVisible(options)
		name_pattern = options.get("name_pattern", "$category/*")
	
		if not "$category" in name_pattern and not "${category}" in name_pattern:
			raise SetConfigError(_("name_pattern doesn't include $category placeholder"))
	
		for cat in categories:
			myset = CategorySet(cat, trees[repository].dbapi, only_visible=visible)
			myname = name_pattern.replace("$category", cat)
			myname = myname.replace("${category}", cat)
			rValue[myname] = myset
		return rValue
	multiBuilder = classmethod(multiBuilder)

class AgeSet(EverythingSet):
	_operations = ["merge", "unmerge"]

	def __init__(self, vardb, mode="older", age=7):
		super(AgeSet, self).__init__(vardb)
		self._mode = mode
		self._age = age

	def _filter(self, atom):
	
		cpv = self._db.match(atom)[0]
		path = self._db.getpath(cpv, filename="COUNTER")
		age = (time.time() - os.stat(path).st_mtime) / (3600 * 24)
		if ((self._mode == "older" and age <= self._age) \
			or (self._mode == "newer" and age >= self._age)):
			return False
		else:
			return True
	
	def singleBuilder(cls, options, settings, trees):
		mode = options.get("mode", "older")
		if str(mode).lower() not in ["newer", "older"]:
			raise SetConfigError(_("invalid 'mode' value %s (use either 'newer' or 'older')") % mode)
		try:
			age = int(options.get("age", "7"))
		except ValueError as e:
			raise SetConfigError(_("value of option 'age' is not an integer"))
		return AgeSet(vardb=trees["vartree"].dbapi, mode=mode, age=age)

	singleBuilder = classmethod(singleBuilder)

class RebuiltBinaries(EverythingSet):
	_operations = ('merge',)
	_aux_keys = ('BUILD_TIME',)

	def __init__(self, vardb, bindb=None):
		super(RebuiltBinaries, self).__init__(vardb, bindb=bindb)
		self._bindb = bindb

	def _filter(self, atom):
		cpv = self._db.match(atom)[0]
		inst_build_time, = self._db.aux_get(cpv, self._aux_keys)
		try:
			bin_build_time, = self._bindb.aux_get(cpv, self._aux_keys)
		except KeyError:
			return False
		return bool(bin_build_time and (inst_build_time != bin_build_time))

	def singleBuilder(cls, options, settings, trees):
		return RebuiltBinaries(trees["vartree"].dbapi,
			bindb=trees["bintree"].dbapi)

	singleBuilder = classmethod(singleBuilder)
