# -*- encoding: utf-8 -*-

from argparse import ArgumentParser
import ConfigParser

from logger import *
from service_manager import ServiceManager


class Service(object):
	"""Base class for all services."""
	def __init__(self, config_path, logfile_path=None, logging_lvl="info", run_as_daemon=False, pidfile=None):
		"""Constructor
			config_path - path to config file. Example config file is in config.ini
			logfile_path - path to main logfile
			logging_lvl - string containing logging level. For more see logger.py
			run_as_daemon - boolean flag. Set to True if you want the service to run in background
							(daemon mode)
			pidfile - path to PIDfile
		"""
		self.config = self._read_config(config_path)

		self.logfile_path = logfile_path
		self.logging_lvl = Logger.str2logging_lvl(logging_lvl)

		self.run_as_daemon = run_as_daemon
		self.pidfile = pidfile

	def process(self, task_file, task_options, output_file):
		"""Processing function. This is specific to service and should be implemented in the subclass."""
		raise NotImplementedError("`process` method should be implemented in the subclass.")

	def run(self):
		manager = ServiceManager(self, self.config, self.logfile_path, self.logging_lvl, self.run_as_daemon, self.pidfile)
		manager.run()

	def _process_handler(self, task_file, task_options, output_file):
		"""Runs processing function, if the processing function raises an exception it is returned instead
		of ignored."""
		try:
			self.process(task_file, task_options, output_file)
			return task_file
		except Exception as e:
			e.traceback = traceback.format_exc()
			e.task_file = task_file
			return e

	def _read_config(self, config_path):
		"""Read config file and create dictionary of option values"""
		S_SERVICE = 'service'
		S_TOOL = 'tool'

		config = dict()
		with open(config_path) as config_file:
			config_parser = ConfigParser.RawConfigParser()
			config_parser.readfp(config_file)
			for name, value in config_parser.items(S_SERVICE):
				config[name] = value
			for name, value in config_parser.items(S_TOOL):
				config[name] = value
			config['request_headers'] = {'Content-type': 'application/json'}
			config['data'] = {"tool": config['tool']}
			config['workers'] = int(config['workers']) if 'workers' in config else None
			config['sleep'] = int(config['sleep'])/1000.0 if 'sleep' in config else 0.01
		return config

def create_service_option_parser():
	"""Creates default argument parser for convinience. Parser can be easily extended (see
		ArgumentParser in python documentation)
	"""
	parser = ArgumentParser()
	parser.add_argument("-p", "--pidfile", action="store", dest="pidfile",
						default=None, type=str, help="path to pidfile")
	parser.add_argument("-d", "--daemon", action="store_true", dest="daemon",
						help="enable daemon mode")
	parser.add_argument("-c", "--config", action="store", dest="config_path",
						type=str, default="./config.ini", help="path to config file")
	parser.add_argument("-l", "--logging", action="store", dest="logging_lvl",
						type=str, default="info", help="set logging level, possible: \
						debug, info (default), warning, error")
	parser.add_argument("--log-file", action="store", dest="log_file",
						type=str, default="./", help="path to main log file")
	return parser

def run_service(service_class):
	"""Creates given service class instance and runs it with options defined in command line.
		Assumes that the default ArgumentParser (as in create_service_option_parser) is used.
	"""
	parser = create_service_option_parser()
	args = parser.parse_args()
	config_path = args.config_path
	logfile_path = args.log_file
	logging_lvl = args.logging_lvl
	run_as_daemon = args.daemon
	pidfile = args.pidfile

	service = service_class(config_path, logfile_path, logging_lvl, run_as_daemon, pidfile)
	service.run()
