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

import bisect
import collections
import sys

class DbapiProvidesIndex(object):
	"""
	The DbapiProvidesIndex class is used to wrap existing dbapi
	interfaces, index packages by the sonames that they provide, and
	implement the dbapi.match method for SonameAtom instances. Since
	this class acts as a wrapper, it can be used conditionally, so that
	soname indexing overhead is avoided when soname dependency
	resolution is disabled.

	Since it's possible for soname atom match results to consist of
	packages with multiple categories or names, it is essential that
	Package.__lt__ behave meaningfully when Package.cp is dissimilar,
	so that match results will be correctly ordered by version for each
	value of Package.cp.
	"""

	_copy_attrs = ('aux_get', 'aux_update', 'categories', 'cpv_all',
		'cpv_exists', 'cp_all', 'cp_list', 'getfetchsizes',
		'settings', '_aux_cache_keys', '_clear_cache',
		'_cpv_sort_ascending', '_pkg_str', '_pkg_str_aux_keys')

	def __init__(self, db):
		self._db = db
		for k in self._copy_attrs:
			try:
				setattr(self, k, getattr(db, k))
			except AttributeError:
				pass
		self._provides_index = collections.defaultdict(list)

	def match(self, atom, use_cache=DeprecationWarning):
		if atom.soname:
			result = self._match_soname(atom)
		else:
			result = self._db.match(atom)
		return result

	def _match_soname(self, atom):
		result = self._provides_index.get(atom)
		if result is None:
			result = []
		else:
			result = [pkg.cpv for pkg in result]
		return result

	def _provides_inject(self, pkg):
		index = self._provides_index
		for atom in pkg.provides:
			# Use bisect.insort for ordered match results.
			bisect.insort(index[atom], pkg)

class PackageDbapiProvidesIndex(DbapiProvidesIndex):
	"""
	This class extends DbapiProvidesIndex in order to make it suitable
	for wrapping a PackageVirtualDbapi instance.
	"""

	_copy_attrs = DbapiProvidesIndex._copy_attrs + (
		"clear", "get", "_cpv_map")

	def clear(self):
		self._db.clear()
		self._provides_index.clear()

	def __bool__(self):
		return bool(self._db)

	if sys.hexversion < 0x3000000:
		__nonzero__ = __bool__

	def __iter__(self):
		return iter(self._db)

	def __contains__(self, item):
		return item in self._db

	def match_pkgs(self, atom):
		return [self._db._cpv_map[cpv] for cpv in self.match(atom)]

	def cpv_inject(self, pkg):
		self._db.cpv_inject(pkg)
		self._provides_inject(pkg)

	def cpv_remove(self, pkg):
		self._db.cpv_remove(pkg)
		index = self._provides_index
		for atom in pkg.provides:
			items = index[atom]
			try:
				items.remove(pkg)
			except ValueError:
				pass
			if not items:
				del index[atom]
