#!python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 Bitergia
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Authors:
#     Luis Cañas-Díaz <lcanas@bitergia.com>
#     Alvaro del Castillo <acs@bitergia.com>
#


import argparse
import configparser
import logging
import logging.handlers
import os
import sys
import traceback

sys.path.insert(1, '.')

from mordred.config import Config
from mordred.error import ElasticSearchError
from mordred.error import DataCollectionError
from mordred.mordred import Mordred


SLEEPFOR_ERROR = """Error: You may be Arthur, King of the Britons. But you still """ + \
"""need the 'sleep_for' variable in sortinghat section\n - Mordred said."""


logger = logging.getLogger(__name__)


def setup_logs(logs_dir, debug_mode, log_file_handler, max_bytes, backup_count):

    if debug_mode:
        logging_mode = logging.DEBUG
    else:
        logging_mode = logging.INFO

    log_file_handler_kwargs = {}
    if log_file_handler == "rotate":
        log_file_handler = logging.handlers.RotatingFileHandler
        log_file_handler_kwargs['maxBytes'] = max_bytes
        log_file_handler_kwargs['backupCount'] = backup_count
    else:
        log_file_handler = logging.FileHandler

    # create logger with 'spam_application'
    logger = logging.getLogger()
    logger.setLevel(logging_mode)
    # create file handler which logs even debug messages

    fh_filepath = os.path.join(logs_dir,'all.log')
    fh = log_file_handler(fh_filepath, **log_file_handler_kwargs)
    fh.setLevel(logging_mode)
    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    # create formatter and add it to the handlers
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    # add the handlers to the logger
    logger.addHandler(fh)
    logger.addHandler(ch)

    pfh_filepath = os.path.join(logs_dir,'perceval.log')
    pfh = log_file_handler(pfh_filepath, **log_file_handler_kwargs)
    fh.setLevel(logging_mode)
    pfh.setFormatter(formatter)
    perceval_logger = logging.getLogger('perceval')
    perceval_logger.addHandler(pfh)

    gfh_filepath = os.path.join(logs_dir,'grimoire.log')
    gfh = log_file_handler(gfh_filepath, **log_file_handler_kwargs)
    fh.setLevel(logging_mode)
    gfh.setFormatter(formatter)
    perceval_logger = logging.getLogger('grimoire')
    perceval_logger.addHandler(gfh)

    wfh_filepath = os.path.join(logs_dir,'mordred.log')
    wfh = log_file_handler(wfh_filepath, **log_file_handler_kwargs)
    wfh.setLevel(logging_mode)
    wfh.setFormatter(formatter)
    workflow_logger = logging.getLogger('mordred')
    workflow_logger.addHandler(wfh)

    logging.getLogger('requests').setLevel(logging.WARNING)
    logging.getLogger('urrlib3').setLevel(logging.WARNING)

    return logger

def parse_args():

    parser = argparse.ArgumentParser(
        description='Mordred, the friendly friend of GrimoireELK',
        epilog='Software metrics for your peace of mind'
        )

    parser.add_argument('-c','--config', help='Configuration files',
                        type=str, nargs='+', default=['mordred.cfg'],
                        dest='config_files')
    parser.add_argument('-t','--template', help='Create template configuration file',
                        dest='config_template_file')
    parser.add_argument('-p','--phases', nargs='*',
                        help='List of phases to execute (update is set to false)')

    args = parser.parse_args()
    return args

if __name__ == '__main__':
    args = parse_args()
    if args.config_template_file is not None:
        Config.create_config_file(args.config_template_file)
        logger.info("Sample config file created in %s", args.config_template_file)
        sys.exit(0)
    elif args.config_files is None:
        logger.error("Option -t or -c is required")
        sys.exit(1)

    try:
        config = Config(args.config_files[0], args.config_files[1:])
        config_dict = config.get_conf()
        logs_dir = config_dict['general']['logs_dir']
        debug_mode = config_dict['general']['debug']
        log_file_handler = config_dict['general']['log_handler']
        log_max_bytes = config_dict['general']['log_max_bytes']
        log_backup_count = config_dict['general']['log_backup_count']
        logger = setup_logs(logs_dir, debug_mode, log_file_handler, log_max_bytes, log_backup_count)
    except RuntimeError as error:
        print("Error while consuming configuration: ", error)
        sys.exit(1)

    if args.phases:
        logger.info("Executing mordred for phases: %s", args.phases)
        # HACK: the internal dict of Config is modified directly
        # In manual phases execute mordred as an script
        config_dict['general']['update'] = False
        for phase in config_dict['phases']:
            config_dict['phases'][phase] = True if phase in args.phases else False

    Mordred(config).start()
