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

from __future__ import print_function


import sys
import textwrap

import portage
from portage import os
from portage.emaint.module import Modules
from portage.emaint.progress import ProgressBar
from portage.emaint.defaults import DEFAULT_OPTIONS
from portage.util._argparse import ArgumentParser

class OptionItem(object):
	"""class to hold module ArgumentParser options data
	"""

	def __init__(self, opt):
		"""
		@type opt: dictionary
		@param opt: options parser options
		"""
		self.short = opt.get('short')
		self.long = opt.get('long')
		self.help = opt.get('help')
		self.status = opt.get('status')
		self.func = opt.get('func')
		self.action = opt.get('action')
		self.type = opt.get('type')
		self.dest = opt.get('dest')

	@property
	def pargs(self):
		pargs = []
		if self.short is not None:
			pargs.append(self.short)
		if self.long is not None:
			pargs.append(self.long)
		return pargs

	@property
	def kwargs(self):
		# Support for keyword arguments varies depending on the action,
		# so only pass in the keywords that are needed, in order
		# to avoid a TypeError.
		kwargs = {}
		if self.help is not None:
			kwargs['help'] = self.help
		if self.action is not None:
			kwargs['action'] = self.action
		if self.type is not None:
			kwargs['type'] = self.type
		if self.dest is not None:
			kwargs['dest'] = self.dest
		return kwargs

def usage(module_controller):
		_usage = "usage: emaint [options] COMMAND"

		desc = "The emaint program provides an interface to system health " + \
			"checks and maintenance. See the emaint(1) man page " + \
			"for additional information about the following commands:"

		_usage += "\n\n"
		for line in textwrap.wrap(desc, 65):
			_usage += "%s\n" % line
		_usage += "\nCommands:\n"
		_usage += "  %s" % "all".ljust(15) + \
			"Perform all supported commands\n"
		textwrap.subsequent_indent = ' '.ljust(17)
		for mod in module_controller.module_names:
			desc = textwrap.wrap(module_controller.get_description(mod), 65)
			_usage += "  %s%s\n" % (mod.ljust(15), desc[0])
			for d in desc[1:]:
				_usage += "  %s%s\n" % (' '.ljust(15), d)
		return _usage


def module_opts(module_controller, module):
	_usage = " %s module options:\n" % module
	opts = module_controller.get_func_descriptions(module)
	if opts == {}:
		opts = DEFAULT_OPTIONS
	for opt in sorted(opts):
		optd = opts[opt]
		opto = "  %s, %s" % (optd['short'], optd['long'])
		_usage += '%s %s\n' % (opto.ljust(15), optd['help'])
	_usage += '\n'
	return _usage


class TaskHandler(object):
	"""Handles the running of the tasks it is given"""

	def __init__(self, show_progress_bar=True, verbose=True, callback=None):
		self.show_progress_bar = show_progress_bar
		self.verbose = verbose
		self.callback = callback
		self.isatty = os.environ.get('TERM') != 'dumb' and sys.stdout.isatty()
		self.progress_bar = ProgressBar(self.isatty, title="Emaint", max_desc_length=27)

	def run_tasks(self, tasks, func, status=None, verbose=True, options=None):
		"""Runs the module tasks"""
		if tasks is None or func is None:
			return
		for task in tasks:
			inst = task()
			show_progress = self.show_progress_bar and self.isatty
			# check if the function is capable of progressbar 
			# and possibly override it off
			if show_progress and hasattr(inst, 'can_progressbar'):
				show_progress = inst.can_progressbar(func)
			if show_progress:
				self.progress_bar.reset()
				self.progress_bar.set_label(func + " " + inst.name())
				onProgress = self.progress_bar.start()
			else:
				onProgress = None
			kwargs = {
				'onProgress': onProgress,
				# pass in a copy of the options so a module can not pollute or change
				# them for other tasks if there is more to do.
				'options': options.copy()
				}
			result = getattr(inst, func)(**kwargs)
			if show_progress:
				# make sure the final progress is displayed
				self.progress_bar.display()
				print()
				self.progress_bar.stop()
			if self.callback:
				self.callback(result)


def print_results(results):
	if results:
		print()
		print("\n".join(results))
		print("\n")


def emaint_main(myargv):

	# Similar to emerge, emaint needs a default umask so that created
	# files (such as the world file) have sane permissions.
	os.umask(0o22)

	module_controller = Modules(namepath="portage.emaint.modules")
	module_names = module_controller.module_names[:]
	module_names.insert(0, "all")


	parser = ArgumentParser(usage=usage(module_controller))
	# add default options
	parser_options = []
	for opt in DEFAULT_OPTIONS:
		parser_options.append(OptionItem(DEFAULT_OPTIONS[opt]))
	for mod in module_names[1:]:
		desc = module_controller.get_func_descriptions(mod)
		if desc:
			for opt in desc:
				parser_options.append(OptionItem(desc[opt]))
	for opt in parser_options:
		parser.add_argument(*opt.pargs, **opt.kwargs)

	options, args = parser.parse_known_args(args=myargv)

	if options.version:
		print(portage.VERSION)
		return os.EX_OK

	if len(args) != 1:
		parser.error("Incorrect number of arguments")
	if args[0] not in module_names:
		parser.error("%s target is not a known target" % args[0])

	check_opt = None
	func = status = long_action = None
	for opt in parser_options:
		if opt.long == '--check':
			# Default action
			check_opt = opt
		if opt.status and getattr(options, opt.long.lstrip("-"), False):
			if long_action is not None:
				parser.error("--%s and %s are exclusive options" %
					(long_action, opt.long))
			status = opt.status
			func = opt.func
			long_action = opt.long.lstrip('-')

	if long_action is None:
		long_action = 'check'
		func = check_opt.func
		status = check_opt.status

	if args[0] == "all":
		tasks = []
		for m in module_names[1:]:
			#print("DEBUG: module: %s, functions: " % (m, str(module_controller.get_functions(m))))
			if long_action in module_controller.get_functions(m):
				tasks.append(module_controller.get_class(m))
	elif long_action in module_controller.get_functions(args[0]):
		tasks = [module_controller.get_class(args[0] )]
	else:
		portage.util.writemsg(
			"\nERROR: module '%s' does not have option '--%s'\n\n" %
			(args[0], long_action), noiselevel=-1)
		portage.util.writemsg(module_opts(module_controller, args[0]),
			noiselevel=-1)
		sys.exit(1)

	# need to pass the parser options dict to the modules
	# so they are available if needed.
	task_opts = options.__dict__
	taskmaster = TaskHandler(callback=print_results)
	taskmaster.run_tasks(tasks, func, status, options=task_opts)
