# Copyright 2017 Mycroft AI Inc.
#
# Licensed 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 inspect
import logging
import sys


class LOG:
    """
    Custom logger class that acts like logging.Logger
    The logger name is automatically generated by the module of the caller

    Usage:
        >>> LOG.debug('My message: %s', debug_str)
        13:12:43.673 - :<module>:1 - DEBUG - My message: hi
        >>> LOG('custom_name').debug('Another message')
        13:13:10.462 - custom_name - DEBUG - Another message
    """
    base_path = "stdout"
    fmt = '%(asctime)s.%(msecs)03d - ' \
          '%(name)s - %(levelname)s - %(message)s'
    datefmt = '%Y-%m-%d %H:%M:%S'
    formatter = logging.Formatter(fmt, datefmt)
    name = 'little_questions'
    level = "DEBUG"
    _loggers = {}

    @classmethod
    def set_level(cls, level="INFO"):
        cls.level = level
        for n in cls._loggers:
            cls._loggers[n].setLevel(cls.level)

    @classmethod
    def create_logger(cls, name):
        if name in cls._loggers:
            return cls._loggers[name]
        logger = logging.getLogger(name)
        logger.propagate = False
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(cls.formatter)
        logger.addHandler(stdout_handler)
        logger.setLevel(cls.level)
        cls._loggers[name] = logger
        return logger

    @classmethod
    def _log(cls):
        name = ""
        if cls.name is not None:
            name = cls.name + " - "

        # Stack:
        # [0] - _log()
        # [1] - debug(), info(), warning(), or error()
        # [2] - caller
        stack = inspect.stack()

        # Record:
        # [0] - frame object
        # [1] - filename
        # [2] - line number
        # [3] - function
        # ...
        record = stack[2]
        name += record[3] + ':' + str(record[2])

        logger = cls.create_logger(name)
        return logger

    @classmethod
    def info(cls, *args, **kwargs):
        cls._log().info(*args, **kwargs)

    @classmethod
    def debug(cls, *args, **kwargs):
        cls._log().debug(*args, **kwargs)

    @classmethod
    def warning(cls, *args, **kwargs):
        cls._log().warning(*args, **kwargs)

    @classmethod
    def error(cls, *args, **kwargs):
        cls._log().error(*args, **kwargs)

    @classmethod
    def exception(cls, *args, **kwargs):
        cls._log().exception(*args, **kwargs)

[(35, 'logging.Formatter', 'logging.Formatter', False, 'import logging\n'), (50, 'logging.getLogger', 'logging.getLogger', False, 'import logging\n'), (52, 'logging.StreamHandler', 'logging.StreamHandler', False, 'import logging\n'), (69, 'inspect.stack', 'inspect.stack', False, 'import inspect\n')]