# 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 argument"
		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
