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

from __future__ import print_function, unicode_literals

import logging
from itertools import chain

import portage
from portage import normalize_path
from portage import os
from portage.output import green
from portage.util.futures.extendedfutures import ExtendedFuture
from repoman.metadata import get_metadata_xsd
from repoman.modules.commit import repochecks
from repoman.modules.commit import manifest
from repoman.profile import check_profiles, dev_profile_keywords, setup_profile
from repoman.repos import repo_metadata
from repoman.modules.scan.module import ModuleConfig
from repoman.modules.scan.scan import scan
from repoman.modules.vcs.vcs import vcs_files_to_cps


DATA_TYPES = {'dict': dict, 'Future': ExtendedFuture, 'list': list, 'set': set}


class Scanner(object):
	'''Primary scan class.  Operates all the small Q/A tests and checks'''

	def __init__(self, repo_settings, myreporoot, config_root, options,
				vcs_settings, mydir, env):
		'''Class __init__'''
		self.repo_settings = repo_settings
		self.config_root = config_root
		self.options = options
		self.vcs_settings = vcs_settings
		self.env = env

		# Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to
		# behave incrementally.
		self.repoman_incrementals = tuple(
			x for x in portage.const.INCREMENTALS if x != 'ACCEPT_KEYWORDS')

		self.categories = []
		for path in self.repo_settings.repo_config.eclass_db.porttrees:
			self.categories.extend(portage.util.grabfile(
				os.path.join(path, 'profiles', 'categories')))
		self.repo_settings.repoman_settings.categories = frozenset(
			portage.util.stack_lists([self.categories], incremental=1))
		self.categories = self.repo_settings.repoman_settings.categories

		self.portdb = repo_settings.portdb
		self.portdb.settings = self.repo_settings.repoman_settings

		digest_only = self.options.mode != 'manifest-check' \
			and self.options.digest == 'y'
		self.generate_manifest = digest_only or self.options.mode in \
			("manifest", 'commit', 'fix')

		# We really only need to cache the metadata that's necessary for visibility
		# filtering. Anything else can be discarded to reduce memory consumption.
		if not self.generate_manifest:
			# Don't do this when generating manifests, since that uses
			# additional keys if spawn_nofetch is called (RESTRICT and
			# DEFINED_PHASES).
			self.portdb._aux_cache_keys.clear()
			self.portdb._aux_cache_keys.update(
				["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"])

		self.reposplit = myreporoot.split(os.path.sep)
		self.repolevel = len(self.reposplit)

		if self.options.mode == 'commit':
			repochecks.commit_check(self.repolevel, self.reposplit)
			repochecks.conflict_check(self.vcs_settings, self.options)

		# Make startdir relative to the canonical repodir, so that we can pass
		# it to digestgen and it won't have to be canonicalized again.
		if self.repolevel == 1:
			startdir = self.repo_settings.repodir
		else:
			startdir = normalize_path(mydir)
			startdir = os.path.join(
				self.repo_settings.repodir, *startdir.split(os.sep)[-2 - self.repolevel + 3:])

		# get lists of valid keywords, licenses, and use
		new_data = repo_metadata(self.portdb, self.repo_settings.repoman_settings)
		kwlist, liclist, uselist, profile_list, \
			global_pmaskdict, liclist_deprecated = new_data
		self.repo_metadata = {
			'kwlist': kwlist,
			'liclist': liclist,
			'uselist': uselist,
			'profile_list': profile_list,
			'pmaskdict': global_pmaskdict,
			'lic_deprecated': liclist_deprecated,
		}

		self.repo_settings.repoman_settings['PORTAGE_ARCHLIST'] = ' '.join(sorted(kwlist))
		self.repo_settings.repoman_settings.backup_changes('PORTAGE_ARCHLIST')

		profiles = setup_profile(profile_list)

		check_profiles(profiles, self.repo_settings.repoman_settings.archlist())

		scanlist = scan(self.repolevel, self.reposplit, startdir, self.categories, self.repo_settings)

		self.dev_keywords = dev_profile_keywords(profiles)

		self.qatracker = self.vcs_settings.qatracker

		if self.options.echangelog is None and self.repo_settings.repo_config.update_changelog:
			self.options.echangelog = 'y'

		if self.vcs_settings.vcs is None:
			self.options.echangelog = 'n'

		# Initialize the ModuleConfig class here
		# TODO Add layout.conf masters repository.yml config to the list to load/stack
		self.moduleconfig = ModuleConfig(self.repo_settings.masters_list,
										self.repo_settings.repoman_settings.valid_versions,
										repository_modules=self.options.experimental_repository_modules == 'y')

		checks = {}
		# The --echangelog option causes automatic ChangeLog generation,
		# which invalidates changelog.ebuildadded and changelog.missing
		# checks.
		# Note: Some don't use ChangeLogs in distributed SCMs.
		# It will be generated on server side from scm log,
		# before package moves to the rsync server.
		# This is needed because they try to avoid merge collisions.
		# Gentoo's Council decided to always use the ChangeLog file.
		# TODO: shouldn't this just be switched on the repo, iso the VCS?
		is_echangelog_enabled = self.options.echangelog in ('y', 'force')
		self.vcs_settings.vcs_is_cvs_or_svn = self.vcs_settings.vcs in ('cvs', 'svn')
		checks['changelog'] = not is_echangelog_enabled and self.vcs_settings.vcs_is_cvs_or_svn

		if self.options.mode == "manifest" or self.options.quiet:
			pass
		elif self.options.pretend:
			print(green("\nRepoMan does a once-over of the neighborhood..."))
		else:
			print(green("\nRepoMan scours the neighborhood..."))

		self.changed = self.vcs_settings.changes
		# bypass unneeded VCS operations if not needed
		if (self.options.if_modified == "y" or
			self.options.mode not in ("manifest", "manifest-check")):
			self.changed.scan()

		self.have = {
			'pmasked': False,
			'dev_keywords': False,
		}

		# NOTE: match-all caches are not shared due to potential
		# differences between profiles in _get_implicit_iuse.
		self.caches = {
			'arch': {},
			'arch_xmatch': {},
			'shared_xmatch': {"cp-list": {}},
		}

		self.include_arches = None
		if self.options.include_arches:
			self.include_arches = set()
			self.include_arches.update(*[x.split() for x in self.options.include_arches])

		# Disable the "self.modules['Ebuild'].notadded" check when not in commit mode and
		# running `svn status` in every package dir will be too expensive.
		checks['ebuild_notadded'] = not \
			(self.vcs_settings.vcs == "svn" and self.repolevel < 3 and self.options.mode != "commit")

		self.effective_scanlist = scanlist
		if self.options.if_modified == "y":
			self.effective_scanlist = sorted(vcs_files_to_cps(
				chain(self.changed.changed, self.changed.new, self.changed.removed),
				self.repo_settings.repodir,
				self.repolevel, self.reposplit, self.categories))

		# Create our kwargs dict here to initialize the plugins with
		self.kwargs = {
			"repo_settings": self.repo_settings,
			"portdb": self.portdb,
			"qatracker": self.qatracker,
			"vcs_settings": self.vcs_settings,
			"options": self.options,
			"metadata_xsd": get_metadata_xsd(self.repo_settings),
			"uselist": uselist,
			"checks": checks,
			"repo_metadata": self.repo_metadata,
			"profiles": profiles,
			"include_arches": self.include_arches,
			"caches": self.caches,
			"repoman_incrementals": self.repoman_incrementals,
			"env": self.env,
			"have": self.have,
			"dev_keywords": self.dev_keywords,
			"linechecks": self.moduleconfig.linechecks,
		}
		# initialize the plugin checks here
		self.modules = {}
		self._ext_futures = {}
		self.pkg_level_futures = None

	def set_kwargs(self, mod):
		'''Creates a limited set of kwargs to pass to the module's __init__()

		@param mod: module name string
		@returns: dictionary
		'''
		kwargs = {}
		for key in self.moduleconfig.controller.modules[mod]['mod_kwargs']:
			kwargs[key] = self.kwargs[key]
		return kwargs

	def set_func_kwargs(self, mod, dynamic_data=None):
		'''Updates the dynamic_data dictionary with any new key, value pairs.
		Creates a limited set of kwargs to pass to the modulefunctions to run

		@param mod: module name string
		@param dynamic_data: dictionary structure
		@returns: dictionary
		'''
		func_kwargs = self.moduleconfig.controller.modules[mod]['func_kwargs']
		# determine new keys
		required = set(list(func_kwargs))
		exist = set(list(dynamic_data))
		new = required.difference(exist)
		# update dynamic_data with initialized entries
		for key in new:
			logging.debug("set_func_kwargs(); adding: %s, %s",
				key, func_kwargs[key])
			if func_kwargs[key][0] in ['Future', 'ExtendedFuture']:
				if key not in self._ext_futures:
					logging.debug(
						"Adding a new key: %s to the ExtendedFuture dict", key)
					self._ext_futures[key] = func_kwargs[key]
				self._set_future(dynamic_data, key, func_kwargs[key])
			else:  # builtin python data type
				dynamic_data[key] = DATA_TYPES[func_kwargs[key][0]]()
		kwargs = {}
		for key in required:
			kwargs[key] = dynamic_data[key]
		return kwargs

	def reset_futures(self, dynamic_data):
		'''Reset any Future data types

		@param dynamic_data: dictionary
		'''
		for key in list(self._ext_futures):
			if key not in self.pkg_level_futures:
				self._set_future(dynamic_data, key, self._ext_futures[key])

	@staticmethod
	def _set_future(dynamic_data, key, data):
		'''Set a dynamic_data key to a new ExtendedFuture instance

		@param dynamic_data: dictionary
		@param key: tuple of (dictionary-key, default-value)
		'''
		if data[0] in ['Future', 'ExtendedFuture']:
			if data[1] in ['UNSET']:
				dynamic_data[key] = ExtendedFuture()
			else:
				if data[1] in DATA_TYPES:
					default = DATA_TYPES[data[1]]()
				else:
					default = data[1]
				dynamic_data[key] = ExtendedFuture(default)

	def scan_pkgs(self, can_force):
		for xpkg in self.effective_scanlist:
			xpkg_continue = False
			# ebuilds and digests added to cvs respectively.
			logging.info("checking package %s", xpkg)
			# save memory by discarding xmatch caches from previous package(s)
			self.caches['arch_xmatch'].clear()
			catdir, pkgdir = xpkg.split("/")
			checkdir = self.repo_settings.repodir + "/" + xpkg
			checkdir_relative = ""
			if self.repolevel < 3:
				checkdir_relative = os.path.join(pkgdir, checkdir_relative)
			if self.repolevel < 2:
				checkdir_relative = os.path.join(catdir, checkdir_relative)
			checkdir_relative = os.path.join(".", checkdir_relative)

			# Run the status check
			if self.kwargs['checks']['ebuild_notadded']:
				self.vcs_settings.status.check(checkdir, checkdir_relative, xpkg)

			if self.generate_manifest:
				manifest.Manifest(**self.kwargs).update_manifest(checkdir)
				if self.options.mode == 'manifest':
					continue
			checkdirlist = os.listdir(checkdir)

			dynamic_data = {
				'changelog_modified': False,
				'checkdirlist': ExtendedFuture(checkdirlist),
				'checkdir': checkdir,
				'xpkg': xpkg,
				'changed': self.changed,
				'checkdir_relative': checkdir_relative,
				'can_force': can_force,
				'repolevel': self.repolevel,
				'catdir': catdir,
				'pkgdir': pkgdir,
				'validity_future': ExtendedFuture(True),
				'y_ebuild': None,
				# this needs to be reset at the pkg level only,
				# easiest is to just initialize it here
				'muselist': ExtendedFuture(set()),
				'src_uri_error': ExtendedFuture(),
				}
			self.pkg_level_futures = [
				'checkdirlist',
				'muselist',
				'pkgs',
				'src_uri_error',
				'validity_future',
				]
			# need to set it up for ==> self.modules or some other ordered list
			logging.debug("***** starting pkgs_loop: %s", self.moduleconfig.pkgs_loop)
			for mod in self.moduleconfig.pkgs_loop:
				mod_class = self.moduleconfig.controller.get_class(mod)
				logging.debug("Initializing class name: %s", mod_class.__name__)
				self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
				logging.debug("scan_pkgs; module: %s", mod_class.__name__)
				do_it, functions = self.modules[mod_class.__name__].runInPkgs
				if do_it:
					for func in functions:
						_continue = func(**self.set_func_kwargs(mod, dynamic_data))
						if _continue:
							# If we can't access all the metadata then it's totally unsafe to
							# commit since there's no way to generate a correct Manifest.
							# Do not try to do any more QA checks on this package since missing
							# metadata leads to false positives for several checks, and false
							# positives confuse users.
							xpkg_continue = True
							break

			if xpkg_continue:
				continue

			# Sort ebuilds in ascending order for the KEYWORDS.dropped check.
			pkgs = dynamic_data['pkgs'].get()
			ebuildlist = sorted(pkgs.values())
			ebuildlist = [pkg.pf for pkg in ebuildlist]

			if self.kwargs['checks']['changelog'] and "ChangeLog" not in checkdirlist:
				self.qatracker.add_error("changelog.missing", xpkg + "/ChangeLog")

			changelog_path = os.path.join(checkdir_relative, "ChangeLog")
			dynamic_data["changelog_modified"] = changelog_path in self.changed.changelogs

			self._scan_ebuilds(ebuildlist, dynamic_data)
		return


	def _scan_ebuilds(self, ebuildlist, dynamic_data):

		for y_ebuild in ebuildlist:
			self.reset_futures(dynamic_data)
			dynamic_data['y_ebuild'] = y_ebuild
			y_ebuild_continue = False

			# initialize per ebuild plugin checks here
			# need to set it up for ==> self.modules_list or some other ordered list
			for mod in self.moduleconfig.ebuilds_loop:
				if mod:
					mod_class = self.moduleconfig.controller.get_class(mod)
					if mod_class.__name__ not in self.modules:
						logging.debug("Initializing class name: %s", mod_class.__name__)
						self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
				logging.debug("scan_ebuilds: module: %s", mod_class.__name__)
				do_it, functions = self.modules[mod_class.__name__].runInEbuilds
				logging.debug("do_it: %s, functions: %s", do_it, [x.__name__ for x in functions])
				if do_it:
					for func in functions:
						logging.debug("\tRunning function: %s", func)
						_continue = func(**self.set_func_kwargs(mod, dynamic_data))
						if _continue:
							# If we can't access all the metadata then it's totally unsafe to
							# commit since there's no way to generate a correct Manifest.
							# Do not try to do any more QA checks on this package since missing
							# metadata leads to false positives for several checks, and false
							# positives confuse users.
							y_ebuild_continue = True
							# logging.debug("\t>>> Continuing")
							break

			if y_ebuild_continue:
				continue

			logging.debug("Finished ebuild plugin loop, continuing...")

		# Final checks
		# initialize per pkg plugin final checks here
		# need to set it up for ==> self.modules_list or some other ordered list
		xpkg_complete = False
		for mod in self.moduleconfig.final_loop:
			if mod:
				mod_class = self.moduleconfig.controller.get_class(mod)
				if mod_class.__name__ not in self.modules:
					logging.debug("Initializing class name: %s", mod_class.__name__)
					self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
			logging.debug("scan_ebuilds final checks: module: %s", mod_class.__name__)
			do_it, functions = self.modules[mod_class.__name__].runInFinal
			logging.debug("do_it: %s, functions: %s", do_it, [x.__name__ for x in functions])
			if do_it:
				for func in functions:
					logging.debug("\tRunning function: %s", func)
					_continue = func(**self.set_func_kwargs(mod, dynamic_data))
					if _continue:
						xpkg_complete = True
						# logging.debug("\t>>> Continuing")
						break

		if xpkg_complete:
			return
		return
