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

import logging
import sys

import portage
from portage import os
from portage.util import normalize_path, writemsg_level
from portage.util._argparse import ArgumentParser
from portage.util._async.run_main_scheduler import run_main_scheduler
from portage.util._async.SchedulerInterface import SchedulerInterface
from portage.util._eventloop.global_event_loop import global_event_loop
from .Config import Config
from .MirrorDistTask import MirrorDistTask

if sys.hexversion >= 0x3000000:
	long = int

seconds_per_day = 24 * 60 * 60

common_options = (
	{
		"longopt"  : "--dry-run",
		"help"     : "perform a trial run with no changes made (usually combined "
			"with --verbose)",
		"action"   : "store_true"
	},
	{
		"longopt"  : "--verbose",
		"shortopt" : "-v",
		"help"     : "display extra information on stderr "
			"(multiple occurences increase verbosity)",
		"action"   : "count",
		"default"  : 0,
	},
	{
		"longopt"  : "--ignore-default-opts",
		"help"     : "do not use the EMIRRORDIST_DEFAULT_OPTS environment variable",
		"action"   : "store_true"
	},
	{
		"longopt"  : "--distfiles",
		"help"     : "distfiles directory to use (required)",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--jobs",
		"shortopt" : "-j",
		"help"     : "number of concurrent jobs to run",
		"type"     : int
	},
	{
		"longopt"  : "--load-average",
		"shortopt" : "-l",
		"help"     : "load average limit for spawning of new concurrent jobs",
		"metavar"  : "LOAD",
		"type"     : float
	},
	{
		"longopt"  : "--tries",
		"help"     : "maximum number of tries per file, 0 means unlimited (default is 10)",
		"default"  : 10,
		"type"     : int
	},
	{
		"longopt"  : "--repo",
		"help"     : "name of repo to operate on"
	},
	{
		"longopt"  : "--config-root",
		"help"     : "location of portage config files",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--portdir",
		"help"     : "override the PORTDIR variable (deprecated in favor of --repositories-configuration)",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--portdir-overlay",
		"help"     : "override the PORTDIR_OVERLAY variable (deprecated in favor of --repositories-configuration)"
	},
	{
		"longopt"  : "--repositories-configuration",
		"help"     : "override configuration of repositories (in format of repos.conf)"
	},
	{
		"longopt"  : "--strict-manifests",
		"help"     : "manually override \"strict\" FEATURES setting",
		"choices"  : ("y", "n"),
		"metavar"  : "<y|n>",
	},
	{
		"longopt"  : "--failure-log",
		"help"     : "log file for fetch failures, with tab-delimited "
			"output, for reporting purposes",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--success-log",
		"help"     : "log file for fetch successes, with tab-delimited "
			"output, for reporting purposes",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--scheduled-deletion-log",
		"help"     : "log file for scheduled deletions, with tab-delimited "
			"output, for reporting purposes",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--delete",
		"help"     : "enable deletion of unused distfiles",
		"action"   : "store_true"
	},
	{
		"longopt"  : "--deletion-db",
		"help"     : "database file used to track lifetime of files "
			"scheduled for delayed deletion",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--deletion-delay",
		"help"     : "delay time for deletion, measured in seconds",
		"metavar"  : "SECONDS"
	},
	{
		"longopt"  : "--temp-dir",
		"help"     : "temporary directory for downloads",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--mirror-overrides",
		"help"     : "file holding a list of mirror overrides",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--mirror-skip",
		"help"     : "comma delimited list of mirror targets to skip "
			"when fetching"
	},
	{
		"longopt"  : "--restrict-mirror-exemptions",
		"help"     : "comma delimited list of mirror targets for which to "
			"ignore RESTRICT=\"mirror\""
	},
	{
		"longopt"  : "--verify-existing-digest",
		"help"     : "use digest as a verification of whether existing "
			"distfiles are valid",
		"action"   : "store_true"
	},
	{
		"longopt"  : "--distfiles-local",
		"help"     : "distfiles-local directory to use",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--distfiles-db",
		"help"     : "database file used to track which ebuilds a "
			"distfile belongs to",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--recycle-dir",
		"help"     : "directory for extended retention of files that "
			"are removed from distdir with the --delete option",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--recycle-db",
		"help"     : "database file used to track lifetime of files "
			"in recycle dir",
		"metavar"  : "FILE"
	},
	{
		"longopt"  : "--recycle-deletion-delay",
		"help"     : "delay time for deletion of unused files from "
			"recycle dir, measured in seconds (defaults to "
			"the equivalent of 60 days)",
		"default"  : 60 * seconds_per_day,
		"metavar"  : "SECONDS",
		"type"     : int
	},
	{
		"longopt"  : "--fetch-log-dir",
		"help"     : "directory for individual fetch logs",
		"metavar"  : "DIR"
	},
	{
		"longopt"  : "--whitelist-from",
		"help"     : "specifies a file containing a list of files to "
			"whitelist, one per line, # prefixed lines ignored",
		"action"   : "append",
		"metavar"  : "FILE"
	},
)

def parse_args(args):
	description = "emirrordist - a fetch tool for mirroring " \
		"of package distfiles"
	usage = "emirrordist [options] <action>"
	parser = ArgumentParser(description=description, usage=usage)

	actions = parser.add_argument_group('Actions')
	actions.add_argument("--version",
		action="store_true",
		help="display portage version and exit")
	actions.add_argument("--mirror",
		action="store_true",
		help="mirror distfiles for the selected repository")

	common = parser.add_argument_group('Common options')
	for opt_info in common_options:
		opt_pargs = [opt_info["longopt"]]
		if opt_info.get("shortopt"):
			opt_pargs.append(opt_info["shortopt"])
		opt_kwargs = {"help" : opt_info["help"]}
		for k in ("action", "choices", "default", "metavar", "type"):
			if k in opt_info:
				opt_kwargs[k] = opt_info[k]
		common.add_argument(*opt_pargs, **opt_kwargs)

	options, args = parser.parse_known_args(args)

	return (parser, options, args)

def emirrordist_main(args):

	# The calling environment is ignored, so the program is
	# completely controlled by commandline arguments.
	env = {}

	if not sys.stdout.isatty():
		portage.output.nocolor()
		env['NOCOLOR'] = 'true'

	parser, options, args = parse_args(args)

	if options.version:
		sys.stdout.write("Portage %s\n" % portage.VERSION)
		return os.EX_OK

	config_root = options.config_root

	if options.portdir is not None:
		writemsg_level("emirrordist: warning: --portdir option is deprecated in favor of --repositories-configuration option\n",
			level=logging.WARNING, noiselevel=-1)
	if options.portdir_overlay is not None:
		writemsg_level("emirrordist: warning: --portdir-overlay option is deprecated in favor of --repositories-configuration option\n",
			level=logging.WARNING, noiselevel=-1)	

	if options.repositories_configuration is not None:
		env['PORTAGE_REPOSITORIES'] = options.repositories_configuration
	elif options.portdir_overlay is not None:
		env['PORTDIR_OVERLAY'] = options.portdir_overlay

	if options.portdir is not None:
		env['PORTDIR'] = options.portdir

	settings = portage.config(config_root=config_root,
		local_config=False, env=env)

	default_opts = None
	if not options.ignore_default_opts:
		default_opts = settings.get('EMIRRORDIST_DEFAULT_OPTS', '').split()

	if default_opts:
		parser, options, args = parse_args(default_opts + args)

		settings = portage.config(config_root=config_root,
			local_config=False, env=env)

	if options.repo is None:
		if len(settings.repositories.prepos) == 2:
			for repo in settings.repositories:
				if repo.name != "DEFAULT":
					options.repo = repo.name
					break

		if options.repo is None:
			parser.error("--repo option is required")

	repo_path = settings.repositories.treemap.get(options.repo)
	if repo_path is None:
		parser.error("Unable to locate repository named '%s'" % (options.repo,))

	if options.jobs is not None:
		options.jobs = int(options.jobs)

	if options.load_average is not None:
		options.load_average = float(options.load_average)

	if options.failure_log is not None:
		options.failure_log = normalize_path(
			os.path.abspath(options.failure_log))

		parent_dir = os.path.dirname(options.failure_log)
		if not (os.path.isdir(parent_dir) and
			os.access(parent_dir, os.W_OK|os.X_OK)):
			parser.error(("--failure-log '%s' parent is not a "
				"writable directory") % options.failure_log)

	if options.success_log is not None:
		options.success_log = normalize_path(
			os.path.abspath(options.success_log))

		parent_dir = os.path.dirname(options.success_log)
		if not (os.path.isdir(parent_dir) and
			os.access(parent_dir, os.W_OK|os.X_OK)):
			parser.error(("--success-log '%s' parent is not a "
				"writable directory") % options.success_log)

	if options.scheduled_deletion_log is not None:
		options.scheduled_deletion_log = normalize_path(
			os.path.abspath(options.scheduled_deletion_log))

		parent_dir = os.path.dirname(options.scheduled_deletion_log)
		if not (os.path.isdir(parent_dir) and
			os.access(parent_dir, os.W_OK|os.X_OK)):
			parser.error(("--scheduled-deletion-log '%s' parent is not a "
				"writable directory") % options.scheduled_deletion_log)

		if options.deletion_db is None:
			parser.error("--scheduled-deletion-log requires --deletion-db")

	if options.deletion_delay is not None:
		options.deletion_delay = long(options.deletion_delay)
		if options.deletion_db is None:
			parser.error("--deletion-delay requires --deletion-db")

	if options.deletion_db is not None:
		if options.deletion_delay is None:
			parser.error("--deletion-db requires --deletion-delay")
		options.deletion_db = normalize_path(
			os.path.abspath(options.deletion_db))

	if options.temp_dir is not None:
		options.temp_dir = normalize_path(
			os.path.abspath(options.temp_dir))

		if not (os.path.isdir(options.temp_dir) and
			os.access(options.temp_dir, os.W_OK|os.X_OK)):
			parser.error(("--temp-dir '%s' is not a "
				"writable directory") % options.temp_dir)

	if options.distfiles is not None:
		options.distfiles = normalize_path(
			os.path.abspath(options.distfiles))

		if not (os.path.isdir(options.distfiles) and
			os.access(options.distfiles, os.W_OK|os.X_OK)):
			parser.error(("--distfiles '%s' is not a "
				"writable directory") % options.distfiles)
	else:
		parser.error("missing required --distfiles parameter")

	if options.mirror_overrides is not None:
		options.mirror_overrides = normalize_path(
			os.path.abspath(options.mirror_overrides))

		if not (os.access(options.mirror_overrides, os.R_OK) and
			os.path.isfile(options.mirror_overrides)):
			parser.error(
				"--mirror-overrides-file '%s' is not a readable file" %
				options.mirror_overrides)

	if options.distfiles_local is not None:
		options.distfiles_local = normalize_path(
			os.path.abspath(options.distfiles_local))

		if not (os.path.isdir(options.distfiles_local) and
			os.access(options.distfiles_local, os.W_OK|os.X_OK)):
			parser.error(("--distfiles-local '%s' is not a "
				"writable directory") % options.distfiles_local)

	if options.distfiles_db is not None:
		options.distfiles_db = normalize_path(
			os.path.abspath(options.distfiles_db))

	if options.tries is not None:
		options.tries = int(options.tries)

	if options.recycle_dir is not None:
		options.recycle_dir = normalize_path(
			os.path.abspath(options.recycle_dir))
		if not (os.path.isdir(options.recycle_dir) and
			os.access(options.recycle_dir, os.W_OK|os.X_OK)):
			parser.error(("--recycle-dir '%s' is not a "
				"writable directory") % options.recycle_dir)

	if options.recycle_db is not None:
		if options.recycle_dir is None:
			parser.error("--recycle-db requires "
				"--recycle-dir to be specified")
		options.recycle_db = normalize_path(
			os.path.abspath(options.recycle_db))

	if options.recycle_deletion_delay is not None:
		options.recycle_deletion_delay = \
			long(options.recycle_deletion_delay)

	if options.fetch_log_dir is not None:
		options.fetch_log_dir = normalize_path(
			os.path.abspath(options.fetch_log_dir))

		if not (os.path.isdir(options.fetch_log_dir) and
			os.access(options.fetch_log_dir, os.W_OK|os.X_OK)):
			parser.error(("--fetch-log-dir '%s' is not a "
				"writable directory") % options.fetch_log_dir)

	if options.whitelist_from:
		normalized_paths = []
		for x in options.whitelist_from:
			path = normalize_path(os.path.abspath(x))
			normalized_paths.append(path)
			if not (os.access(path, os.R_OK) and os.path.isfile(path)):
				parser.error(
					"--whitelist-from '%s' is not a readable file" % x)
		options.whitelist_from = normalized_paths

	if options.strict_manifests is not None:
		if options.strict_manifests == "y":
			settings.features.add("strict")
		else:
			settings.features.discard("strict")

	settings.lock()

	portdb = portage.portdbapi(mysettings=settings)

	# Limit ebuilds to the specified repo.
	portdb.porttrees = [repo_path]

	portage.util.initialize_logger()

	if options.verbose > 0:
		l = logging.getLogger()
		l.setLevel(l.getEffectiveLevel() - 10 * options.verbose)

	with Config(options, portdb,
		SchedulerInterface(global_event_loop())) as config:

		if not options.mirror:
			parser.error('No action specified')

		returncode = os.EX_OK

		if options.mirror:
			signum = run_main_scheduler(MirrorDistTask(config))
			if signum is not None:
				sys.exit(128 + signum)

	return returncode
