#!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, '.')

# Quick fix for avoiding weird warnings
# https://github.com/chaoss/grimoirelab-sirmordred/issues/192
import warnings
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")

from sirmordred.config import Config
from sirmordred.error import ElasticSearchError
from sirmordred.error import DataCollectionError
from sirmordred.sirmordred import SirMordred


SLEEPFOR_ERROR = """Error: You may be Arthur, King of the Britons. But you still """ + \
"""need the 'sleep_for' variable in sortinghat section\n - Sir 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,'sirmordred.log')
    wfh = log_file_handler(wfh_filepath, **log_file_handler_kwargs)
    wfh.setLevel(logging_mode)
    wfh.setFormatter(formatter)
    workflow_logger = logging.getLogger('sirmordred')
    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='SirMordred, 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 sirmordred for phases: %s", args.phases)
        # HACK: the internal dict of Config is modified directly
        # In manual phases execute sirmordred 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

    SirMordred(config).start()
