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

__all__ = (
	'VirtualsManager',
)

from copy import deepcopy

from portage import os
from portage.dep import Atom
from portage.exception import InvalidAtom
from portage.localization import _
from portage.util import grabdict, stack_dictlist, writemsg
from portage.versions import cpv_getkey

class VirtualsManager(object):

	def __init__(self, *args, **kwargs):
		if kwargs.get("_copy"):
			return

		assert len(args) == 1, "VirtualsManager.__init__ takes one positional arguments"
		assert not kwargs, "unknown keyword argument(s) '%s' passed to VirtualsManager.__init__" % \
			", ".join(kwargs)

		profiles = args[0]
		self._virtuals = None
		self._dirVirtuals = None
		self._virts_p = None

		# Virtuals obtained from the vartree
		self._treeVirtuals = None
		# Virtuals added by the depgraph via self.add_depgraph_virtuals().
		self._depgraphVirtuals = {}

		#Initialise _dirVirtuals.
		self._read_dirVirtuals(profiles)

		#We could initialise _treeVirtuals here, but some consumers want to
		#pass their own vartree.

	def _read_dirVirtuals(self, profiles):
		"""
		Read the 'virtuals' file in all profiles.
		"""
		virtuals_list = []
		for x in profiles:
			virtuals_file = os.path.join(x, "virtuals")
			virtuals_dict = grabdict(virtuals_file)
			atoms_dict = {}
			for k, v in virtuals_dict.items():
				try:
					virt_atom = Atom(k)
				except InvalidAtom:
					virt_atom = None
				else:
					if virt_atom.blocker or \
						str(virt_atom) != str(virt_atom.cp):
						virt_atom = None
				if virt_atom is None:
					writemsg(_("--- Invalid virtuals atom in %s: %s\n") % \
						(virtuals_file, k), noiselevel=-1)
					continue
				providers = []
				for atom in v:
					atom_orig = atom
					if atom[:1] == '-':
						# allow incrementals
						atom = atom[1:]
					try:
						atom = Atom(atom)
					except InvalidAtom:
						atom = None
					else:
						if atom.blocker:
							atom = None
					if atom is None:
						writemsg(_("--- Invalid atom in %s: %s\n") % \
							(virtuals_file, atom_orig), noiselevel=-1)
					else:
						if atom_orig == str(atom):
							# normal atom, so return as Atom instance
							providers.append(atom)
						else:
							# atom has special prefix, so return as string
							providers.append(atom_orig)
				if providers:
					atoms_dict[virt_atom] = providers
			if atoms_dict:
				virtuals_list.append(atoms_dict)

		self._dirVirtuals = stack_dictlist(virtuals_list, incremental=True)

		for virt in self._dirVirtuals:
			# Preference for virtuals decreases from left to right.
			self._dirVirtuals[virt].reverse()

	def __deepcopy__(self, memo=None):
		if memo is None:
			memo = {}
		result = VirtualsManager(_copy=True)
		memo[id(self)] = result

		# immutable attributes (internal policy ensures lack of mutation)
		# _treeVirtuals is initilised by _populate_treeVirtuals().
		# Before that it's 'None'.
		result._treeVirtuals = self._treeVirtuals
		memo[id(self._treeVirtuals)] = self._treeVirtuals
		# _dirVirtuals is initilised by __init__.
		result._dirVirtuals = self._dirVirtuals
		memo[id(self._dirVirtuals)] = self._dirVirtuals

		# mutable attributes (change when add_depgraph_virtuals() is called)
		result._virtuals = deepcopy(self._virtuals, memo)
		result._depgraphVirtuals = deepcopy(self._depgraphVirtuals, memo)
		result._virts_p = deepcopy(self._virts_p, memo)

		return result

	def _compile_virtuals(self):
		"""Stack installed and profile virtuals.  Preference for virtuals
		decreases from left to right.
		Order of preference:
		1. installed and in profile
		2. installed only
		3. profile only
		"""

		assert self._treeVirtuals is not None, "_populate_treeVirtuals() must be called before " + \
			"any query about virtuals"

		# Virtuals by profile+tree preferences.
		ptVirtuals   = {}

		for virt, installed_list in self._treeVirtuals.items():
			profile_list = self._dirVirtuals.get(virt, None)
			if not profile_list:
				continue
			for cp in installed_list:
				if cp in profile_list:
					ptVirtuals.setdefault(virt, [])
					ptVirtuals[virt].append(cp)

		virtuals = stack_dictlist([ptVirtuals, self._treeVirtuals,
			self._dirVirtuals, self._depgraphVirtuals])
		self._virtuals = virtuals
		self._virts_p = None

	def getvirtuals(self):
		"""
		Computes self._virtuals if necessary and returns it.
		self._virtuals is only computed on the first call.
		"""
		if self._virtuals is None:
			self._compile_virtuals()

		return self._virtuals

	def _populate_treeVirtuals(self, vartree):
		"""
		Initialize _treeVirtuals from the given vartree.
		It must not have been initialized already, otherwise
		our assumptions about immutability don't hold.
		"""
		assert self._treeVirtuals is None, "treeVirtuals must not be reinitialized"

		self._treeVirtuals = {}

		for provide, cpv_list in vartree.get_all_provides().items():
			try:
				provide = Atom(provide)
			except InvalidAtom:
				continue
			self._treeVirtuals[provide.cp] = \
				[Atom(cpv_getkey(cpv)) for cpv in cpv_list]

	def populate_treeVirtuals_if_needed(self, vartree):
		"""
		Initialize _treeVirtuals if it hasn't been done already.
		This is a hack for consumers that already have an populated vartree.
		"""
		if self._treeVirtuals is not None:
			return

		self._populate_treeVirtuals(vartree)

	def add_depgraph_virtuals(self, mycpv, virts):
		"""This updates the preferences for old-style virtuals,
		affecting the behavior of dep_expand() and dep_check()
		calls. It can change dbapi.match() behavior since that
		calls dep_expand(). However, dbapi instances have
		internal match caches that are not invalidated when
		preferences are updated here. This can potentially
		lead to some inconsistency (relevant to bug #1343)."""

		#Ensure that self._virtuals is populated.
		if self._virtuals is None:
			self.getvirtuals()

		modified = False
		cp = Atom(cpv_getkey(mycpv))
		for virt in virts:
			try:
				virt = Atom(virt).cp
			except InvalidAtom:
				continue
			providers = self._virtuals.get(virt)
			if providers and cp in providers:
				continue
			providers = self._depgraphVirtuals.get(virt)
			if providers is None:
				providers = []
				self._depgraphVirtuals[virt] = providers
			if cp not in providers:
				providers.append(cp)
				modified = True

		if modified:
			self._compile_virtuals()

	def get_virts_p(self):
		if self._virts_p is not None:
			return self._virts_p

		virts = self.getvirtuals()
		virts_p = {}
		for x in virts:
			vkeysplit = x.split("/")
			if vkeysplit[1] not in virts_p:
				virts_p[vkeysplit[1]] = virts[x]
		self._virts_p = virts_p
		return virts_p
