# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import os
import copy
import logging
from logutils import dictconfig

HIGH_VERBOSE = 3
MEDIUM_VERBOSE = 2
LOW_VERBOSE = 1
NO_VERBOSE = 0

LOGGER_CONFIG_TEMPLATE = {
    "version": 1,
    "formatters": {
        "file": {
            "format": "%(asctime)s [%(levelname)s] %(message)s"
        },
        "console": {
            "format": "%(message)s"
        }
    },
    "handlers": {
        "file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "file",
            "maxBytes": "5000000",
            "backupCount": "20"
        },
        "console": {
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout",
            "formatter": "console"
        }
    },
    "disable_existing_loggers": False
}


class Logging(object):

    def __init__(self, config):
        self._log_file = None
        self._verbosity_level = NO_VERBOSE
        self._all_loggers_names = []
        self._configure_loggers(config)
        self._lgr = logging.getLogger('aria.cli.main')

    @property
    def logger(self):
        return self._lgr

    @property
    def log_file(self):
        return self._log_file

    @property
    def verbosity_level(self):
        return self._verbosity_level

    @verbosity_level.setter
    def verbosity_level(self, level):
        self._verbosity_level = level
        if self.is_high_verbose_level():
            for logger_name in self._all_loggers_names:
                logging.getLogger(logger_name).setLevel(logging.DEBUG)

    def is_high_verbose_level(self):
        return self.verbosity_level == HIGH_VERBOSE

    def _configure_loggers(self, config):
        loggers_config = config.logging.loggers
        logfile = config.logging.filename

        logger_dict = copy.deepcopy(LOGGER_CONFIG_TEMPLATE)
        if logfile:
            # set filename on file handler
            logger_dict['handlers']['file']['filename'] = logfile
            logfile_dir = os.path.dirname(logfile)
            if not os.path.exists(logfile_dir):
                os.makedirs(logfile_dir)
            self._log_file = logfile
        else:
            del logger_dict['handlers']['file']

        # add handlers to all loggers
        loggers = {}
        for logger_name in loggers_config:
            loggers[logger_name] = dict(handlers=list(logger_dict['handlers'].keys()))
            self._all_loggers_names.append(logger_name)
        logger_dict['loggers'] = loggers

        # set level for all loggers
        for logger_name, logging_level in loggers_config.iteritems():
            log = logging.getLogger(logger_name)
            level = logging._levelNames[logging_level.upper()]
            log.setLevel(level)

        dictconfig.dictConfig(logger_dict)


class ModelLogIterator(object):

    def __init__(self, model_storage, execution_id, filters=None, sort=None, offset=0):
        self._last_visited_id = offset
        self._model_storage = model_storage
        self._execution_id = execution_id
        self._additional_filters = filters or {}
        self._sort = sort or {}

    def __iter__(self):
        filters = dict(execution_fk=self._execution_id, id=dict(gt=self._last_visited_id))
        filters.update(self._additional_filters)

        for log in self._model_storage.log.iter(filters=filters, sort=self._sort):
            self._last_visited_id = log.id
            yield log
