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

from __future__ import division

import re
import time

from portage import os
from portage.versions import best, catsplit, vercmp
from portage.dep import Atom, use_reduce
from portage.exception import InvalidAtom
from portage.localization import _
from portage._sets.base import PackageSet
from portage._sets import SetConfigError, get_boolean
import portage

__all__ = ["CategorySet", "ChangedDepsSet", "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 = []
		pkg_str = self._db._pkg_str
		cp_list = self._db.cp_list

		for cp in self._db.cp_all():
			for cpv in cp_list(cp):
				# NOTE: Create SLOT atoms even when there is only one
				# SLOT installed, in order to avoid the possibility
				# of unwanted upgrades as reported in bug #338959.
				pkg = pkg_str(cpv, None)
				atom = Atom("%s:%s" % (pkg.cp, pkg.slot))
				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
		pkg_str = vardb._pkg_str
		if exclude_paths is None:
			for link, p in vardb._owners.iter_owners(paths):
				pkg = pkg_str(link.mycpv, None)
				rValue.add("%s:%s" % (pkg.cp, pkg.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):
				pkg = pkg_str(link.mycpv, None)
				atom = "%s:%s" % (pkg.cp, pkg.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
		pkg_str = self._vardb._pkg_str
		for cp in self._vardb.cp_all():
			for cpv in cp_list(cp):
				pkg = pkg_str(cpv, None)
				slot_atom = "%s:%s" % (pkg.cp, pkg.slot)
				ebuild = xmatch(xmatch_level, slot_atom)
				if not ebuild:
					continue
				if vercmp(cpv.version, ebuild.version) > 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"]
	_aux_keys = ('BUILD_TIME',)

	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]
		try:
			date, = self._db.aux_get(cpv, self._aux_keys)
			date = int(date)
		except (KeyError, ValueError):
			return bool(self._mode == "older")
		age = (time.time() - date) / (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 DateSet(EverythingSet):
	_operations = ["merge", "unmerge"]
	_aux_keys = ('BUILD_TIME',)

	def __init__(self, vardb, date, mode="older"):
		super(DateSet, self).__init__(vardb)
		self._mode = mode
		self._date = date

	def _filter(self, atom):

		cpv = self._db.match(atom)[0]
		try:
			date, = self._db.aux_get(cpv, self._aux_keys)
			date = int(date)
		except (KeyError, ValueError):
			return bool(self._mode == "older")
		# Make sure inequality is _strict_ to exclude tested package
		if ((self._mode == "older" and date < self._date) \
			or (self._mode == "newer" and date > self._date)):
			return True
		else:
			return False

	def singleBuilder(cls, options, settings, trees):
		vardbapi = trees["vartree"].dbapi
		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)

		formats = []
		if options.get("package") is not None:
			formats.append("package")
		if options.get("filestamp") is not None:
			formats.append("filestamp")
		if options.get("seconds") is not None:
			formats.append("seconds")
		if options.get("date") is not None:
			formats.append("date")

		if not formats:
			raise SetConfigError(_("none of these options specified: 'package', 'filestamp', 'seconds', 'date'"))
		elif len(formats) > 1:
			raise SetConfigError(_("no more than one of these options is allowed: 'package', 'filestamp', 'seconds', 'date'"))

		format = formats[0]

		if (format == "package"):
			package = options.get("package")
			try:
				cpv = vardbapi.match(package)[0]
				date, = vardbapi.aux_get(cpv, ('BUILD_TIME',))
				date = int(date)
			except (KeyError, ValueError):
				raise SetConfigError(_("cannot determine installation date of package %s") % package)
		elif (format == "filestamp"):
			filestamp = options.get("filestamp")
			try:
				date = int(os.stat(filestamp).st_mtime)
			except (OSError, ValueError):
				raise SetConfigError(_("cannot determine 'filestamp' of '%s'") % filestamp)
		elif (format == "seconds"):
			try:
				date = int(options.get("seconds"))
			except ValueError:
				raise SetConfigError(_("option 'seconds' must be an integer"))
		else:
			dateopt = options.get("date")
			try:
				dateformat = options.get("dateformat", "%x %X")
				date = int(time.mktime(time.strptime(dateopt, dateformat)))
			except ValueError:
				raise SetConfigError(_("'date=%s' does not match 'dateformat=%s'") % (dateopt, dateformat))
		return DateSet(vardb=vardbapi, date=date, mode=mode)

	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)

class ChangedDepsSet(PackageSet):

	_operations = ["merge", "unmerge"]

	description = "Package set which contains all installed " + \
		"packages for which the vdb *DEPEND entries are outdated " + \
		"compared to corresponding portdb entries."

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

	def load(self):
		depvars = ('RDEPEND', 'PDEPEND')

		# regexp used to match atoms using subslot operator :=
		subslot_repl_re = re.compile(r':[^[]*=')

		atoms = []
		for cpv in self._vardb.cpv_all():
			# no ebuild, no update :).
			if not self._portdb.cpv_exists(cpv):
				continue

			# USE flags used to build the ebuild and EAPI
			# (needed for Atom & use_reduce())
			use, eapi = self._vardb.aux_get(cpv, ('USE', 'EAPI'))
			usel = use.split()

			# function used to recursively process atoms in nested lists.
			def clean_subslots(depatom, usel=None):
				if isinstance(depatom, list):
					# process the nested list.
					return [clean_subslots(x, usel) for x in depatom]
				else:
					try:
						# this can be either an atom or some special operator.
						# in the latter case, we get InvalidAtom and pass it as-is.
						a = Atom(depatom)
					except InvalidAtom:
						return depatom
					else:
						# if we're processing portdb, we need to evaluate USE flag
						# dependency conditionals to make them match vdb. this
						# requires passing the list of USE flags, so we reuse it
						# as conditional for the operation as well.
						if usel is not None:
							a = a.evaluate_conditionals(usel)

						# replace slot operator := dependencies with plain :=
						# since we can't properly compare expanded slots
						# in vardb to abstract slots in portdb.
						return subslot_repl_re.sub(':=', a)

			# get all *DEPEND variables from vdb & portdb and compare them.
			# we need to do some cleaning up & expansion to make matching
			# meaningful since vdb dependencies are conditional-free.
			vdbvars = [clean_subslots(use_reduce(x, uselist=usel, eapi=eapi))
					for x in self._vardb.aux_get(cpv, depvars)]
			pdbvars = [clean_subslots(use_reduce(x, uselist=usel, eapi=eapi), usel)
					for x in self._portdb.aux_get(cpv, depvars)]

			# if dependencies don't match, trigger the rebuild.
			if vdbvars != pdbvars:
				atoms.append('=%s' % cpv)

		self._setAtoms(atoms)

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

	singleBuilder = classmethod(singleBuilder)
