# -*- coding:utf-8 -*-


import io
import logging
import re
import sys
import textwrap

# import our initialized portage instance
from repoman._portage import portage

from portage import os
from portage import _encodings
from portage import _unicode_encode
from portage.checksum import get_valid_checksum_keys

from repoman.errors import err
from repoman.profile import ProfileDesc, valid_profile_types

GPG_KEY_ID_REGEX = r'(0x)?([0-9a-fA-F]{8}){1,5}!?'
bad = portage.output.create_color_func("BAD")


class RepoSettings(object):
	'''Holds our repo specific settings'''

	def __init__(
		self, config_root, portdir, portdir_overlay,
		repoman_settings=None, vcs_settings=None, options=None,
		qadata=None):
		self.config_root = config_root
		self.repoman_settings = repoman_settings
		self.vcs_settings = vcs_settings

		self.repositories = self.repoman_settings.repositories

		# Ensure that current repository is in the list of enabled repositories.
		self.repodir = os.path.realpath(portdir_overlay)
		try:
			self.repositories.get_repo_for_location(self.repodir)
		except KeyError:
			self._add_repo(config_root, portdir_overlay)

		# Determine the master config loading list
		self.masters_list = []
		# get out repo masters value
		masters = self.repositories.get_repo_for_location(self.repodir).masters
		for repo in masters:
			self.masters_list.append(os.path.join(repo.location, 'metadata', 'repoman'))
		self.masters_list.append(os.path.join(self.repodir, 'metadata', 'repoman'))

		logging.debug("RepoSettings: init(); load qadata")
		# load the repo specific configuration
		self.qadata = qadata
		if not self.qadata.load_repo_config(self.masters_list, options, repoman_settings.valid_versions):
			logging.error("Aborting...")
			sys.exit(1)
		logging.debug("RepoSettings: qadata loaded: %s", qadata.no_exec)

		self.root = self.repoman_settings['EROOT']
		self.trees = {
			self.root: {'porttree': portage.portagetree(settings=self.repoman_settings)}
		}
		self.portdb = self.trees[self.root]['porttree'].dbapi

		# Constrain dependency resolution to the master(s)
		# that are specified in layout.conf.
		self.repo_config = self.repositories.get_repo_for_location(self.repodir)
		self.portdb.porttrees = list(self.repo_config.eclass_db.porttrees)
		self.portdir = self.portdb.porttrees[0]
		self.commit_env = os.environ.copy()
		# list() is for iteration on a copy.
		for repo in list(self.repositories):
			# all paths are canonical
			if repo.location not in self.repo_config.eclass_db.porttrees:
				del self.repositories[repo.name]

		if self.repo_config.sign_commit and options.mode in ("commit", "fix", "manifest"):
			if vcs_settings.vcs:
				func = getattr(self, '_vcs_gpg_%s' % vcs_settings.vcs)
				func()
			else:
				logging.warning("No VCS type detected, unable to sign the commit")

		# In order to disable manifest signatures, repos may set
		# "sign-manifests = false" in metadata/layout.conf. This
		# can be used to prevent merge conflicts like those that
		# thin-manifests is designed to prevent.
		self.sign_manifests = "sign" in self.repoman_settings.features and \
			self.repo_config.sign_manifest

		if self.repo_config.sign_manifest and self.repo_config.name == "gentoo" and \
			options.mode in ("commit",) and not self.sign_manifests:
			msg = (
				"The '%s' repository has manifest signatures enabled, "
				"but FEATURES=sign is currently disabled. In order to avoid this "
				"warning, enable FEATURES=sign in make.conf. Alternatively, "
				"repositories can disable manifest signatures by setting "
				"'sign-manifests = false' in metadata/layout.conf.") % (
					self.repo_config.name,)
			for line in textwrap.wrap(msg, 60):
				logging.warn(line)

		is_commit = options.mode in ("commit",)
		valid_gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY") and re.match(
			r'^%s$' % GPG_KEY_ID_REGEX, self.repoman_settings["PORTAGE_GPG_KEY"])

		if self.sign_manifests and is_commit and not valid_gpg_key:
			logging.error(
				"PORTAGE_GPG_KEY value is invalid: %s" %
				self.repoman_settings["PORTAGE_GPG_KEY"])
			sys.exit(1)

		manifest_hashes = self.repo_config.manifest_hashes
		manifest_required_hashes = self.repo_config.manifest_required_hashes
		if manifest_hashes is None:
			manifest_hashes = portage.const.MANIFEST2_HASH_DEFAULTS
			manifest_required_hashes = manifest_hashes

		if options.mode in ("commit", "fix", "manifest"):
			missing_required_hashes = manifest_required_hashes.difference(
				manifest_hashes)
			if missing_required_hashes:
				msg = (
					"The 'manifest-hashes' setting in the '%s' repository's "
					"metadata/layout.conf does not contain the '%s' hashes which "
					"are listed in 'manifest-required-hashes'. Please fix that "
					"file if you want to generate valid manifests for "
					"this repository.") % (
					self.repo_config.name, ' '.join(missing_required_hashes))
				for line in textwrap.wrap(msg, 70):
					logging.error(line)
				sys.exit(1)

			unsupported_hashes = manifest_hashes.difference(
				get_valid_checksum_keys())
			if unsupported_hashes:
				msg = (
					"The 'manifest-hashes' setting in the '%s' repository's "
					"metadata/layout.conf contains one or more hash types '%s' "
					"which are not supported by this portage version. You will "
					"have to upgrade portage if you want to generate valid "
					"manifests for this repository.") % (
					self.repo_config.name, " ".join(sorted(unsupported_hashes)))
				for line in textwrap.wrap(msg, 70):
					logging.error(line)
				sys.exit(1)

	def _add_repo(self, config_root, portdir_overlay):
		self.repo_conf = portage.repository.config
		self.repo_name = self.repo_conf.RepoConfig._read_valid_repo_name(
			portdir_overlay)[0]
		self.layout_conf_data = self.repo_conf.parse_layout_conf(portdir_overlay)[0]
		if self.layout_conf_data['repo-name']:
			self.repo_name = self.layout_conf_data['repo-name']
		tmp_conf_file = io.StringIO(textwrap.dedent("""
			[%s]
			location = %s
			""") % (self.repo_name, portdir_overlay))
		# Ensure that the repository corresponding to $PWD overrides a
		# repository of the same name referenced by the existing PORTDIR
		# or PORTDIR_OVERLAY settings.
		self.repoman_settings['PORTDIR_OVERLAY'] = "%s %s" % (
			self.repoman_settings.get('PORTDIR_OVERLAY', ''),
			portage._shell_quote(portdir_overlay))
		self.repositories = self.repo_conf.load_repository_config(
			self.repoman_settings, extra_files=[tmp_conf_file])
		# We have to call the config constructor again so that attributes
		# dependent on config.repositories are initialized correctly.
		self.repoman_settings = portage.config(
			config_root=config_root, local_config=False,
			repositories=self.repositories)

	##########
	# future vcs plugin functions
	##########

	def _vcs_gpg_bzr(self):
		pass

	def _vcs_gpg_cvs(self):
		pass

	def _vcs_gpg_git(self):
		# NOTE: It's possible to use --gpg-sign=key_id to specify the key in
		# the commit arguments. If key_id is unspecified, then it must be
		# configured by `git config user.signingkey key_id`.
		self.vcs_settings.vcs_local_opts.append("--gpg-sign")
		if self.repoman_settings.get("PORTAGE_GPG_DIR"):
			# Pass GNUPGHOME to git for bug #462362.
			self.commit_env["GNUPGHOME"] = self.repoman_settings["PORTAGE_GPG_DIR"]

		# Pass GPG_TTY to git for bug #477728.
		try:
			self.commit_env["GPG_TTY"] = os.ttyname(sys.stdin.fileno())
		except OSError:
			pass

	def _vcs_gpg_hg(self):
		pass

	def _vcs_gpg_svn(self):
		pass


def list_checks(kwlist, liclist, uselist, repoman_settings):
	liclist_deprecated = set()
	if "DEPRECATED" in repoman_settings._license_manager._license_groups:
		liclist_deprecated.update(
			repoman_settings._license_manager.expandLicenseTokens(["@DEPRECATED"]))

	if not liclist:
		logging.fatal("Couldn't find licenses?")
		sys.exit(1)

	if not kwlist:
		logging.fatal("Couldn't read KEYWORDS from arch.list")
		sys.exit(1)

	if not uselist:
		logging.fatal("Couldn't find use.desc?")
		sys.exit(1)
	return liclist_deprecated


def repo_metadata(portdb, repoman_settings):
	# get lists of valid keywords, licenses, and use
	kwlist = set()
	liclist = set()
	uselist = set()
	profile_list = []
	global_pmasklines = []

	for path in portdb.porttrees:
		try:
			liclist.update(os.listdir(os.path.join(path, "licenses")))
		except OSError:
			pass
		kwlist.update(
			portage.grabfile(os.path.join(path, "profiles", "arch.list")))

		use_desc = portage.grabfile(os.path.join(path, 'profiles', 'use.desc'))
		for x in use_desc:
			x = x.split()
			if x:
				uselist.add(x[0])

		expand_desc_dir = os.path.join(path, 'profiles', 'desc')
		try:
			expand_list = os.listdir(expand_desc_dir)
		except OSError:
			pass
		else:
			for fn in expand_list:
				if not fn[-5:] == '.desc':
					continue
				use_prefix = fn[:-5].lower() + '_'
				for x in portage.grabfile(os.path.join(expand_desc_dir, fn)):
					x = x.split()
					if x:
						uselist.add(use_prefix + x[0])

		global_pmasklines.append(
			portage.util.grabfile_package(
				os.path.join(path, 'profiles', 'package.mask'),
				recursive=1, verify_eapi=True))

		desc_path = os.path.join(path, 'profiles', 'profiles.desc')
		try:
			desc_file = io.open(
				_unicode_encode(
					desc_path, encoding=_encodings['fs'], errors='strict'),
				mode='r', encoding=_encodings['repo.content'], errors='replace')
		except EnvironmentError:
			pass
		else:
			for i, x in enumerate(desc_file):
				if x[0] == "#":
					continue
				arch = x.split()
				if len(arch) == 0:
					continue
				if len(arch) != 3:
					err(
						"wrong format: \"%s\" in %s line %d" %
						(bad(x.strip()), desc_path, i + 1, ))
				elif arch[0] not in kwlist:
					err(
						"invalid arch: \"%s\" in %s line %d" %
						(bad(arch[0]), desc_path, i + 1, ))
				elif arch[2] not in valid_profile_types:
					err(
						"invalid profile type: \"%s\" in %s line %d" %
						(bad(arch[2]), desc_path, i + 1, ))
				profile_desc = ProfileDesc(arch[0], arch[2], arch[1], path)
				if not os.path.isdir(profile_desc.abs_path):
					logging.error(
						"Invalid %s profile (%s) for arch %s in %s line %d",
						arch[2], arch[1], arch[0], desc_path, i + 1)
					continue
				if os.path.exists(
					os.path.join(profile_desc.abs_path, 'deprecated')):
					continue
				profile_list.append(profile_desc)
			desc_file.close()

	global_pmasklines = portage.util.stack_lists(global_pmasklines, incremental=1)
	global_pmaskdict = {}
	for x in global_pmasklines:
		global_pmaskdict.setdefault(x.cp, []).append(x)
	del global_pmasklines

	return (
		kwlist, liclist, uselist, profile_list, global_pmaskdict,
		list_checks(kwlist, liclist, uselist, repoman_settings))
