# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import sys
from itertools import chain
import portage
from portage import _encodings, _unicode_decode, _unicode_encode
from portage.cache.mappings import slot_dict_class
from portage.const import EBUILD_PHASES
from portage.dep import Atom, check_required_use, use_reduce, \
	paren_enclose, _slot_re, _slot_separator, _repo_separator
from portage.eapi import eapi_has_iuse_defaults, eapi_has_required_use
from portage.exception import InvalidDependString
from portage.repository.config import _gen_valid_repo
from _emerge.Task import Task

if sys.hexversion >= 0x3000000:
	basestring = str
	long = int

class Package(Task):

	__hash__ = Task.__hash__
	__slots__ = ("built", "cpv", "depth",
		"installed", "metadata", "onlydeps", "operation",
		"root_config", "type_name",
		"category", "counter", "cp", "cpv_split",
		"inherited", "invalid", "iuse", "masks", "mtime",
		"pf", "pv_split", "root", "slot", "slot_atom", "visible",) + \
	("_raw_metadata", "_use",)

	metadata_keys = [
		"BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "EAPI",
		"INHERITED", "IUSE", "KEYWORDS",
		"LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
		"repository", "PROPERTIES", "RESTRICT", "SLOT", "USE",
		"_mtime_", "DEFINED_PHASES", "REQUIRED_USE"]

	_dep_keys = ('DEPEND', 'PDEPEND', 'RDEPEND',)
	_use_conditional_misc_keys = ('LICENSE', 'PROPERTIES', 'RESTRICT')

	def __init__(self, **kwargs):
		Task.__init__(self, **kwargs)
		# the SlotObject constructor assigns self.root_config from keyword args
		# and is an instance of a '_emerge.RootConfig.RootConfig class
		self.root = self.root_config.root
		self._raw_metadata = _PackageMetadataWrapperBase(self.metadata)
		self.metadata = _PackageMetadataWrapper(self, self._raw_metadata)
		if not self.built:
			self.metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
		self.cp = portage.cpv_getkey(self.cpv)
		slot = self.slot
		if _slot_re.match(slot) is None:
			self._invalid_metadata('SLOT.invalid',
				"SLOT: invalid value: '%s'" % slot)
			# Avoid an InvalidAtom exception when creating slot_atom.
			# This package instance will be masked due to empty SLOT.
			slot = '0'
		if (self.iuse.enabled or self.iuse.disabled) and \
			not eapi_has_iuse_defaults(self.metadata["EAPI"]):
			if not self.installed:
				self._invalid_metadata('EAPI.incompatible',
					"IUSE contains defaults, but EAPI doesn't allow them")
		self.slot_atom = portage.dep.Atom("%s%s%s" % (self.cp, _slot_separator, slot))
		self.category, self.pf = portage.catsplit(self.cpv)
		self.cpv_split = portage.catpkgsplit(self.cpv)
		self.pv_split = self.cpv_split[1:]
		if self.inherited is None:
			self.inherited = frozenset()
		repo = _gen_valid_repo(self.metadata.get('repository', ''))
		if not repo:
			repo = '__unknown__'
		self.metadata['repository'] = repo

		self._validate_deps()
		self.masks = self._masks()
		self.visible = self._visible(self.masks)
		if self.operation is None:
			if self.onlydeps or self.installed:
				self.operation = "nomerge"
			else:
				self.operation = "merge"

	def _validate_deps(self):
		"""
		Validate deps. This does not trigger USE calculation since that
		is expensive for ebuilds and therefore we want to avoid doing
		in unnecessarily (like for masked packages).
		"""
		eapi = self.metadata['EAPI']
		dep_eapi = eapi
		dep_valid_flag = self.iuse.is_valid_flag
		if self.installed:
			# Ignore EAPI.incompatible and conditionals missing
			# from IUSE for installed packages since these issues
			# aren't relevant now (re-evaluate when new EAPIs are
			# deployed).
			dep_eapi = None
			dep_valid_flag = None

		for k in self._dep_keys:
			v = self.metadata.get(k)
			if not v:
				continue
			try:
				use_reduce(v, eapi=dep_eapi, matchall=True,
					is_valid_flag=dep_valid_flag, token_class=Atom)
			except InvalidDependString as e:
				self._metadata_exception(k, e)

		k = 'PROVIDE'
		v = self.metadata.get(k)
		if v:
			try:
				use_reduce(v, eapi=dep_eapi, matchall=True,
					is_valid_flag=dep_valid_flag, token_class=Atom)
			except InvalidDependString as e:
				self._metadata_exception(k, e)

		for k in self._use_conditional_misc_keys:
			v = self.metadata.get(k)
			if not v:
				continue
			try:
				use_reduce(v, eapi=dep_eapi, matchall=True,
					is_valid_flag=dep_valid_flag)
			except InvalidDependString as e:
				self._metadata_exception(k, e)

		k = 'REQUIRED_USE'
		v = self.metadata.get(k)
		if v:
			if not eapi_has_required_use(eapi):
				self._invalid_metadata('EAPI.incompatible',
					"REQUIRED_USE set, but EAPI='%s' doesn't allow it" % eapi)
			else:
				try:
					check_required_use(v, (),
						self.iuse.is_valid_flag)
				except InvalidDependString as e:
					# Force unicode format string for python-2.x safety,
					# ensuring that PortageException.__unicode__() is used
					# when necessary.
					self._invalid_metadata(k + ".syntax",
						_unicode_decode("%s: %s") % (k, e))

		k = 'SRC_URI'
		v = self.metadata.get(k)
		if v:
			try:
				use_reduce(v, is_src_uri=True, eapi=eapi, matchall=True,
					is_valid_flag=self.iuse.is_valid_flag)
			except InvalidDependString as e:
				if not self.installed:
					self._metadata_exception(k, e)

	def copy(self):
		return Package(built=self.built, cpv=self.cpv, depth=self.depth,
			installed=self.installed, metadata=self._raw_metadata,
			onlydeps=self.onlydeps, operation=self.operation,
			root_config=self.root_config, type_name=self.type_name)

	def _masks(self):
		masks = {}
		settings = self.root_config.settings

		if self.invalid is not None:
			masks['invalid'] = self.invalid

		if not settings._accept_chost(self.cpv, self.metadata):
			masks['CHOST'] = self.metadata['CHOST']

		eapi = self.metadata["EAPI"]
		if not portage.eapi_is_supported(eapi):
			masks['EAPI.unsupported'] = eapi
		if portage._eapi_is_deprecated(eapi):
			masks['EAPI.deprecated'] = eapi

		missing_keywords = settings._getMissingKeywords(
			self.cpv, self.metadata)
		if missing_keywords:
			masks['KEYWORDS'] = missing_keywords

		try:
			missing_properties = settings._getMissingProperties(
				self.cpv, self.metadata)
			if missing_properties:
				masks['PROPERTIES'] = missing_properties
		except InvalidDependString:
			# already recorded as 'invalid'
			pass

		mask_atom = settings._getMaskAtom(self.cpv, self.metadata)
		if mask_atom is not None:
			masks['package.mask'] = mask_atom

		system_mask = settings._getProfileMaskAtom(
			self.cpv, self.metadata)
		if system_mask is not None:
			masks['profile.system'] = system_mask

		try:
			missing_licenses = settings._getMissingLicenses(
				self.cpv, self.metadata)
			if missing_licenses:
				masks['LICENSE'] = missing_licenses
		except InvalidDependString:
			# already recorded as 'invalid'
			pass

		if not masks:
			masks = None

		return masks

	def _visible(self, masks):

		if masks is not None:

			if 'EAPI.unsupported' in masks:
				return False

			if 'invalid' in masks:
				return False

			if not self.installed and ( \
				'CHOST' in masks or \
				'EAPI.deprecated' in masks or \
				'KEYWORDS' in masks or \
				'PROPERTIES' in masks):
				return False

			if 'package.mask' in masks or \
				'profile.system' in masks or \
				'LICENSE' in masks:
				return False

		return True

	def get_keyword_mask(self):
		"""returns None, 'missing', or 'unstable'."""

		missing = self.root_config.settings._getRawMissingKeywords(
				self.cpv, self.metadata)

		if not missing:
			return None

		if '**' in missing:
			return 'missing'

		global_accept_keywords = frozenset(
			self.root_config.settings.get("ACCEPT_KEYWORDS", "").split())

		for keyword in missing:
			if keyword.lstrip("~") in global_accept_keywords:
				return 'unstable'

		return 'missing'

	def isHardMasked(self):
		"""returns a bool if the cpv is in the list of
		expanded pmaskdict[cp] available ebuilds"""
		pmask = self.root_config.settings._getRawMaskAtom(
			self.cpv, self.metadata)
		return pmask is not None


	def _metadata_exception(self, k, e):

		# For unicode safety with python-2.x we need to avoid
		# using the string format operator with a non-unicode
		# format string, since that will result in the
		# PortageException.__str__() method being invoked,
		# followed by unsafe decoding that may result in a
		# UnicodeDecodeError. Therefore, use _unicode_decode()
		# to ensure that format strings are unicode, so that
		# PortageException.__unicode__() is used when necessary
		# in python-2.x.
		if not self.installed:
			categorized_error = False
			if e.errors:
				for error in e.errors:
					if getattr(error, 'category', None) is None:
						continue
					categorized_error = True
					self._invalid_metadata(error.category,
						_unicode_decode("%s: %s") % (k, error))

			if not categorized_error:
				self._invalid_metadata(k + ".syntax",
					_unicode_decode("%s: %s") % (k, e))
		else:
			# For installed packages, show the path of the file
			# containing the invalid metadata, since the user may
			# want to fix the deps by hand.
			vardb = self.root_config.trees['vartree'].dbapi
			path = vardb.getpath(self.cpv, filename=k)
			self._invalid_metadata(k + ".syntax",
				_unicode_decode("%s: %s in '%s'") % (k, e, path))

	def _invalid_metadata(self, msg_type, msg):
		if self.invalid is None:
			self.invalid = {}
		msgs = self.invalid.get(msg_type)
		if msgs is None:
			msgs = []
			self.invalid[msg_type] = msgs
		msgs.append(msg)

	def __str__(self):
		if self.operation == "merge":
			if self.type_name == "binary":
				cpv_color = "PKG_BINARY_MERGE"
			else:
				cpv_color = "PKG_MERGE"
		elif self.operation == "uninstall":
			cpv_color = "PKG_UNINSTALL"
		else:
			cpv_color = "PKG_NOMERGE"

		s = "(%s, %s" \
			% (portage.output.colorize(cpv_color, self.cpv + _repo_separator + self.repo) , self.type_name)

		if self.type_name == "installed":
			if self.root != "/":
				s += " in '%s'" % self.root
			if self.operation == "uninstall":
				s += " scheduled for uninstall"
		else:
			if self.operation == "merge":
				s += " scheduled for merge"
				if self.root != "/":
					s += " to '%s'" % self.root
		s += ")"
		return s

	if sys.hexversion < 0x3000000:

		__unicode__ = __str__

		def __str__(self):
			return _unicode_encode(self.__unicode__(),
				encoding=_encodings['content'])

	class _use_class(object):

		__slots__ = ("enabled", "_force", "_pkg", "_mask")

		def __init__(self, pkg, use_str):
			self._pkg = pkg
			self._force = None
			self._mask = None
			self.enabled = frozenset(use_str.split())
			if pkg.built:
				# Use IUSE to validate USE settings for built packages,
				# in case the package manager that built this package
				# failed to do that for some reason (or in case of
				# data corruption).
				missing_iuse = pkg.iuse.get_missing_iuse(self.enabled)
				if missing_iuse:
					self.enabled = self.enabled.difference(missing_iuse)

		def _init_force_mask(self):
			pkgsettings = self._pkg._get_pkgsettings()
			self._force = pkgsettings.useforce
			self._mask = pkgsettings.usemask

		@property
		def force(self):
			if self._force is None:
				self._init_force_mask()
			return self._force

		@property
		def mask(self):
			if self._mask is None:
				self._init_force_mask()
			return self._mask

	@property
	def repo(self):
		return self.metadata['repository']

	@property
	def repo_priority(self):
		repo_info = self.root_config.settings.repositories.prepos.get(self.repo)
		if repo_info is None:
			return None
		return repo_info.priority

	@property
	def use(self):
		if self._use is None:
			self.metadata._init_use()
		return self._use

	def _get_pkgsettings(self):
		pkgsettings = self.root_config.trees[
			'porttree'].dbapi.doebuild_settings
		pkgsettings.setcpv(self)
		return pkgsettings

	class _iuse(object):

		__slots__ = ("__weakref__", "all", "enabled", "disabled",
			"tokens") + ("_iuse_implicit_match",)

		def __init__(self, tokens, iuse_implicit_match):
			self.tokens = tuple(tokens)
			self._iuse_implicit_match = iuse_implicit_match
			enabled = []
			disabled = []
			other = []
			for x in tokens:
				prefix = x[:1]
				if prefix == "+":
					enabled.append(x[1:])
				elif prefix == "-":
					disabled.append(x[1:])
				else:
					other.append(x)
			self.enabled = frozenset(enabled)
			self.disabled = frozenset(disabled)
			self.all = frozenset(chain(enabled, disabled, other))

		def is_valid_flag(self, flags):
			"""
			@returns: True if all flags are valid USE values which may
				be specified in USE dependencies, False otherwise.
			"""
			if isinstance(flags, basestring):
				flags = [flags]

			for flag in flags:
				if not flag in self.all and \
					not self._iuse_implicit_match(flag):
					return False
			return True

		def get_missing_iuse(self, flags):
			"""
			@returns: A list of flags missing from IUSE.
			"""
			if isinstance(flags, basestring):
				flags = [flags]
			missing_iuse = []
			for flag in flags:
				if not flag in self.all and \
					not self._iuse_implicit_match(flag):
					missing_iuse.append(flag)
			return missing_iuse

	def _get_hash_key(self):
		hash_key = getattr(self, "_hash_key", None)
		if hash_key is None:
			# For installed (and binary) packages we don't care for the repo
			# when it comes to hashing, because there can only be one cpv.
			# So overwrite the repo_key with type_name.
			repo_key = self.metadata.get('repository')
			if self.type_name != 'ebuild':
				repo_key = self.type_name
			self._hash_key = \
				(self.type_name, self.root, self.cpv, self.operation, repo_key)
		return self._hash_key

	def __len__(self):
		return 4

	def __iter__(self):
		"""
		This is used to generate mtimedb resume mergelist entries, so we
		limit it to 4 items for backward compatibility.
		"""
		return iter(self._get_hash_key()[:4])

	def __lt__(self, other):
		if other.cp != self.cp:
			return False
		if portage.pkgcmp(self.pv_split, other.pv_split) < 0:
			return True
		return False

	def __le__(self, other):
		if other.cp != self.cp:
			return False
		if portage.pkgcmp(self.pv_split, other.pv_split) <= 0:
			return True
		return False

	def __gt__(self, other):
		if other.cp != self.cp:
			return False
		if portage.pkgcmp(self.pv_split, other.pv_split) > 0:
			return True
		return False

	def __ge__(self, other):
		if other.cp != self.cp:
			return False
		if portage.pkgcmp(self.pv_split, other.pv_split) >= 0:
			return True
		return False

_all_metadata_keys = set(x for x in portage.auxdbkeys \
	if not x.startswith("UNUSED_"))
_all_metadata_keys.update(Package.metadata_keys)
_all_metadata_keys = frozenset(_all_metadata_keys)

_PackageMetadataWrapperBase = slot_dict_class(_all_metadata_keys)

class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
	"""
	Detect metadata updates and synchronize Package attributes.
	"""

	__slots__ = ("_pkg",)
	_wrapped_keys = frozenset(
		["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
	_use_conditional_keys = frozenset(
		['LICENSE', 'PROPERTIES', 'PROVIDE', 'RESTRICT',])

	def __init__(self, pkg, metadata):
		_PackageMetadataWrapperBase.__init__(self)
		self._pkg = pkg
		if not pkg.built:
			# USE is lazy, but we want it to show up in self.keys().
			_PackageMetadataWrapperBase.__setitem__(self, 'USE', '')

		self.update(metadata)

	def _init_use(self):
		if self._pkg.built:
			use_str = self['USE']
			self._pkg._use = self._pkg._use_class(
				self._pkg, use_str)
		else:
			try:
				use_str = _PackageMetadataWrapperBase.__getitem__(self, 'USE')
			except KeyError:
				use_str = None
			calculated_use = False
			if not use_str:
				use_str = self._pkg._get_pkgsettings()["PORTAGE_USE"]
				calculated_use = True
			_PackageMetadataWrapperBase.__setitem__(self, 'USE', use_str)
			self._pkg._use = self._pkg._use_class(
				self._pkg, use_str)
			# Initialize these now, since USE access has just triggered
			# setcpv, and we want to cache the result of the force/mask
			# calculations that were done.
			if calculated_use:
				self._pkg._use._init_force_mask()

		return use_str

	def __getitem__(self, k):
		v = _PackageMetadataWrapperBase.__getitem__(self, k)
		if k in self._use_conditional_keys:
			if self._pkg.root_config.settings.local_config and '?' in v:
				try:
					v = paren_enclose(use_reduce(v, uselist=self._pkg.use.enabled, \
						is_valid_flag=self._pkg.iuse.is_valid_flag))
				except InvalidDependString:
					# This error should already have been registered via
					# self._pkg._invalid_metadata().
					pass
				else:
					self[k] = v

		elif k == 'USE' and not self._pkg.built:
			if not v:
				# This is lazy because it's expensive.
				v = self._init_use()

		return v

	def __setitem__(self, k, v):
		_PackageMetadataWrapperBase.__setitem__(self, k, v)
		if k in self._wrapped_keys:
			getattr(self, "_set_" + k.lower())(k, v)

	def _set_inherited(self, k, v):
		if isinstance(v, basestring):
			v = frozenset(v.split())
		self._pkg.inherited = v

	def _set_iuse(self, k, v):
		self._pkg.iuse = self._pkg._iuse(
			v.split(), self._pkg.root_config.settings._iuse_implicit_match)

	def _set_slot(self, k, v):
		self._pkg.slot = v

	def _set_counter(self, k, v):
		if isinstance(v, basestring):
			try:
				v = long(v.strip())
			except ValueError:
				v = 0
		self._pkg.counter = v

	def _set_use(self, k, v):
		# Force regeneration of _use attribute
		self._pkg._use = None
		# Use raw metadata to restore USE conditional values
		# to unevaluated state
		raw_metadata = self._pkg._raw_metadata
		for x in self._use_conditional_keys:
			try:
				self[x] = raw_metadata[x]
			except KeyError:
				pass

	def _set__mtime_(self, k, v):
		if isinstance(v, basestring):
			try:
				v = long(v.strip())
			except ValueError:
				v = 0
		self._pkg.mtime = v

	@property
	def properties(self):
		return self['PROPERTIES'].split()

	@property
	def restrict(self):
		return self['RESTRICT'].split()

	@property
	def defined_phases(self):
		"""
		Returns tokens from DEFINED_PHASES metadata if it is defined,
		otherwise returns a tuple containing all possible phases. This
		makes it easy to do containment checks to see if it's safe to
		skip execution of a given phase.
		"""
		s = self['DEFINED_PHASES']
		if s:
			return s.split()
		return EBUILD_PHASES
