# Copyright © 2020 Interplanetary Database Association e.V.,
# BigchainDB and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0

import bigchaindb
import logging

from bigchaindb.common.exceptions import ConfigurationError
from logging.config import dictConfig as set_logging_config
import os


DEFAULT_LOG_DIR = os.getcwd()

DEFAULT_LOGGING_CONFIG = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'console': {
            'class': 'logging.Formatter',
            'format': ('[%(asctime)s] [%(levelname)s] (%(name)s) '
                       '%(message)s (%(processName)-10s - pid: %(process)d)'),
            'datefmt': '%Y-%m-%d %H:%M:%S',
        },
        'file': {
            'class': 'logging.Formatter',
            'format': ('[%(asctime)s] [%(levelname)s] (%(name)s) '
                       '%(message)s (%(processName)-10s - pid: %(process)d)'),
            'datefmt': '%Y-%m-%d %H:%M:%S',
        }
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'console',
            'level': logging.INFO,
        },
        'file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(DEFAULT_LOG_DIR, 'bigchaindb.log'),
            'mode': 'w',
            'maxBytes':  209715200,
            'backupCount': 5,
            'formatter': 'file',
            'level': logging.INFO,
        },
        'errors': {
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(DEFAULT_LOG_DIR, 'bigchaindb-errors.log'),
            'mode': 'w',
            'maxBytes':  209715200,
            'backupCount': 5,
            'formatter': 'file',
            'level': logging.ERROR,
        }
    },
    'loggers': {},
    'root': {
        'level': logging.DEBUG,
        'handlers': ['console', 'file', 'errors'],
    },
}


def _normalize_log_level(level):
    try:
        return level.upper()
    except AttributeError as exc:
        raise ConfigurationError('Log level must be a string!') from exc


def setup_logging():
    """Function to configure log hadlers.

    .. important::

        Configuration, if needed, should be applied before invoking this
        decorator, as starting the subscriber process for logging will
        configure the root logger for the child process based on the
        state of :obj:`bigchaindb.config` at the moment this decorator
        is invoked.

    """

    logging_configs = DEFAULT_LOGGING_CONFIG
    new_logging_configs = bigchaindb.config['log']

    if 'file' in new_logging_configs:
        filename = new_logging_configs['file']
        logging_configs['handlers']['file']['filename'] = filename

    if 'error_file' in new_logging_configs:
        error_filename = new_logging_configs['error_file']
        logging_configs['handlers']['errors']['filename'] = error_filename

    if 'level_console' in new_logging_configs:
        level = _normalize_log_level(new_logging_configs['level_console'])
        logging_configs['handlers']['console']['level'] = level

    if 'level_logfile' in new_logging_configs:
        level = _normalize_log_level(new_logging_configs['level_logfile'])
        logging_configs['handlers']['file']['level'] = level

    if 'fmt_console' in new_logging_configs:
        fmt = new_logging_configs['fmt_console']
        logging_configs['formatters']['console']['format'] = fmt

    if 'fmt_logfile' in new_logging_configs:
        fmt = new_logging_configs['fmt_logfile']
        logging_configs['formatters']['file']['format'] = fmt

    if 'datefmt_console' in new_logging_configs:
        fmt = new_logging_configs['datefmt_console']
        logging_configs['formatters']['console']['datefmt'] = fmt

    if 'datefmt_logfile' in new_logging_configs:
        fmt = new_logging_configs['datefmt_logfile']
        logging_configs['formatters']['file']['datefmt'] = fmt

    log_levels = new_logging_configs.get('granular_levels', {})

    for logger_name, level in log_levels.items():
        level = _normalize_log_level(level)
        try:
            logging_configs['loggers'][logger_name]['level'] = level
        except KeyError:
            logging_configs['loggers'][logger_name] = {'level': level}

    set_logging_config(logging_configs)
