# -*- 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,
		qawarnings=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)

		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.allow_provide_virtual:
			qawarnings.add("virtual.oldstyle")

		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))
