# Copyright 2005-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# Author(s): Nicholas Carpaski (carpaski@gentoo.org), Brian Harring (ferringb@gentoo.org)

from __future__ import unicode_literals

__all__ = ["cache"]

import stat
import sys
import operator
import warnings
from portage.util import normalize_path
import errno
from portage.exception import FileNotFound, PermissionDenied
from portage import os
from portage import checksum
from portage import _shell_quote

if sys.hexversion >= 0x3000000:
	# pylint: disable=W0622
	long = int


class hashed_path(object):

	def __init__(self, location):
		self.location = location

	def __getattr__(self, attr):
		if attr == 'mtime':
			# use stat.ST_MTIME; accessing .st_mtime gets you a float
			# depending on the python version, and long(float) introduces
			# some rounding issues that aren't present for people using
			# the straight c api.
			# thus use the defacto python compatibility work around;
			# access via index, which guarantees you get the raw long.
			try:
				self.mtime = obj = os.stat(self.location)[stat.ST_MTIME]
			except OSError as e:
				if e.errno in (errno.ENOENT, errno.ESTALE):
					raise FileNotFound(self.location)
				elif e.errno == PermissionDenied.errno:
					raise PermissionDenied(self.location)
				raise
			return obj
		if not attr.islower():
			# we don't care to allow .mD5 as an alias for .md5
			raise AttributeError(attr)
		hashname = attr.upper()
		if hashname not in checksum.get_valid_checksum_keys():
			raise AttributeError(attr)
		val = checksum.perform_checksum(self.location, hashname)[0]
		setattr(self, attr, val)
		return val

	def __repr__(self):
		return "<portage.eclass_cache.hashed_path('%s')>" % (self.location,)

class cache(object):
	"""
	Maintains the cache information about eclasses used in ebuild.
	"""
	def __init__(self, porttree_root, overlays=None):
		if overlays is not None:
			warnings.warn("overlays parameter of portage.eclass_cache.cache constructor is deprecated and no longer used",
			DeprecationWarning, stacklevel=2)

		self.eclasses = {} # {"Name": hashed_path}
		self._eclass_locations = {}
		self._eclass_locations_str = None

		# screw with the porttree ordering, w/out having bash inherit match it, and I'll hurt you.
		# ~harring
		if porttree_root:
			self.porttree_root = porttree_root
			self.porttrees = (normalize_path(self.porttree_root),)
			self._master_eclass_root = os.path.join(self.porttrees[0], "eclass")
			self.update_eclasses()
		else:
			self.porttree_root = None
			self.porttrees = ()
			self._master_eclass_root = None

	def copy(self):
		return self.__copy__()

	def __copy__(self):
		result = self.__class__(None)
		result.eclasses = self.eclasses.copy()
		result._eclass_locations = self._eclass_locations.copy()
		result.porttree_root = self.porttree_root
		result.porttrees = self.porttrees
		result._master_eclass_root = self._master_eclass_root
		return result

	def append(self, other):
		"""
		Append another instance to this instance. This will cause eclasses
		from the other instance to override any eclasses from this instance
		that have the same name.
		"""
		if not isinstance(other, self.__class__):
			raise TypeError(
				"expected type %s, got %s" % (self.__class__, type(other)))
		self.porttrees = self.porttrees + other.porttrees
		self.eclasses.update(other.eclasses)
		self._eclass_locations.update(other._eclass_locations)
		self._eclass_locations_str = None

	def update_eclasses(self):
		self.eclasses = {}
		self._eclass_locations = {}
		master_eclasses = {}
		eclass_len = len(".eclass")
		ignored_listdir_errnos = (errno.ENOENT, errno.ENOTDIR)
		for x in [normalize_path(os.path.join(y,"eclass")) for y in self.porttrees]:
			try:
				eclass_filenames = os.listdir(x)
			except OSError as e:
				if e.errno in ignored_listdir_errnos:
					del e
					continue
				elif e.errno == PermissionDenied.errno:
					raise PermissionDenied(x)
				raise
			for y in eclass_filenames:
				if not y.endswith(".eclass"):
					continue
				obj = hashed_path(os.path.join(x, y))
				obj.eclass_dir = x
				try:
					mtime = obj.mtime
				except FileNotFound:
					continue
				ys = y[:-eclass_len]
				if x == self._master_eclass_root:
					master_eclasses[ys] = mtime
					self.eclasses[ys] = obj
					self._eclass_locations[ys] = x
					continue

				master_mtime = master_eclasses.get(ys)
				if master_mtime is not None:
					if master_mtime == mtime:
						# It appears to be identical to the master,
						# so prefer the master entry.
						continue

				self.eclasses[ys] = obj
				self._eclass_locations[ys] = x

	def validate_and_rewrite_cache(self, ec_dict, chf_type, stores_paths):
		"""
		This will return an empty dict if the ec_dict parameter happens
		to be empty, therefore callers must take care to distinguish
		between empty dict and None return values.
		"""
		if not isinstance(ec_dict, dict):
			return None
		our_getter = operator.attrgetter(chf_type)
		cache_getter = lambda x:x
		if stores_paths:
			cache_getter = operator.itemgetter(1)
		d = {}
		for eclass, ec_data in ec_dict.items():
			cached_data = self.eclasses.get(eclass)
			if cached_data is None:
				return None
			if cache_getter(ec_data) != our_getter(cached_data):
				return None
			d[eclass] = cached_data
		return d

	def get_eclass_data(self, inherits):
		ec_dict = {}
		for x in inherits:
			ec_dict[x] = self.eclasses[x]

		return ec_dict

	@property
	def eclass_locations_string(self):
		if self._eclass_locations_str is None:
			self._eclass_locations_str = " ".join(_shell_quote(x)
				for x in reversed(self.porttrees))
		return self._eclass_locations_str
