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

from __future__ import unicode_literals

from portage.dep import Atom, paren_enclose, use_reduce
from portage.eapi import _get_eapi_attrs
from portage.exception import InvalidData
from _emerge.Package import Package

def strip_slots(dep_struct):
	"""
	Search dep_struct for any slot := operators and remove the
	slot/sub-slot part, while preserving the operator. The result
	is suitable for --changed-deps comparisons.
	"""
	for i, x in enumerate(dep_struct):
		if isinstance(x, list):
			strip_slots(x)
		elif (isinstance(x, Atom) and
			x.slot_operator == "=" and x.slot is not None):
			dep_struct[i] = x.with_slot("=")

def find_built_slot_operator_atoms(pkg):
	atoms = {}
	for k in Package._dep_keys:
		atom_list = list(_find_built_slot_operator(use_reduce(pkg._metadata[k],
			uselist=pkg.use.enabled, eapi=pkg.eapi,
			token_class=Atom)))
		if atom_list:
			atoms[k] = atom_list
	return atoms

def _find_built_slot_operator(dep_struct):
	for x in dep_struct:
		if isinstance(x, list):
			for atom in _find_built_slot_operator(x):
				yield atom
		elif isinstance(x, Atom) and x.slot_operator_built:
			yield x

def ignore_built_slot_operator_deps(dep_struct):
	for i, x in enumerate(dep_struct):
		if isinstance(x, list):
			ignore_built_slot_operator_deps(x)
		elif isinstance(x, Atom) and x.slot_operator_built:
			# There's no way of knowing here whether the SLOT
			# part of the slot/sub-slot pair should be kept, so we
			# ignore both parts.
			dep_struct[i] = x.without_slot

def evaluate_slot_operator_equal_deps(settings, use, trees):

	metadata = settings.configdict['pkg']
	eapi = metadata['EAPI']
	eapi_attrs = _get_eapi_attrs(eapi)
	running_vardb = trees[trees._running_eroot]["vartree"].dbapi
	target_vardb = trees[trees._target_eroot]["vartree"].dbapi
	vardbs = [target_vardb]
	deps = {}
	for k in Package._dep_keys:
		deps[k] = use_reduce(metadata[k],
			uselist=use, eapi=eapi, token_class=Atom)

	for k in Package._runtime_keys:
		_eval_deps(deps[k], vardbs)

	if eapi_attrs.hdepend:
		_eval_deps(deps["HDEPEND"], [running_vardb])
		_eval_deps(deps["DEPEND"], [target_vardb])
	else:
		if running_vardb is not target_vardb:
			vardbs.append(running_vardb)
		_eval_deps(deps["DEPEND"], vardbs)

	result = {}
	for k, v in deps.items():
		result[k] = paren_enclose(v)

	return result

def _eval_deps(dep_struct, vardbs):
	# TODO: we'd use a better || () handling, i.e. || ( A:= B:= ) with both A
	# and B installed should record subslot on A only since the package is
	# supposed to link against that anyway, and we have no guarantee that B
	# has matching ABI.

	for i, x in enumerate(dep_struct):
		if isinstance(x, list):
			_eval_deps(x, vardbs)
		elif isinstance(x, Atom) and x.slot_operator == "=":
			for vardb in vardbs:
				best_version = vardb.match(x)
				if best_version:
					best_version = best_version[-1]
					try:
						best_version = \
							vardb._pkg_str(best_version, None)
					except (KeyError, InvalidData):
						pass
					else:
						slot_part = "%s/%s=" % \
							(best_version.slot, best_version.sub_slot)
						x = x.with_slot(slot_part)
						dep_struct[i] = x
						break
			else:
				# this dep could not be resolved, possibilities include:
				# 1. unsatisfied branch of || () dep,
				# 2. package.provided,
				# 3. --nodeps.
				#
				# just leave it as-is for now. this does not cause any special
				# behavior while keeping the information in vdb -- necessary
				# e.g. for @changed-deps to work properly.
				#
				# TODO: make it actually cause subslot rebuilds when switching
				# || () branches.
				pass
