##
# @file    logging.py
# @version 1.4
# @brief   Implements logging method similar to standard python library
# @author  Jamie Bird (adapted from micropython_lib module)
# @date    Nov 2019
##

import sys
from vts import clock_get as clock
from micropython import const

class s:
   CYAN = str('\033[96m')
   BLUE = str('\033[94m')
   GREEN = str('\033[92m')
   YELLOW = str('\033[93m')
   RED = str('\033[91m')
   MAGENTA = str('\033[35m')
   BOLD = str('\033[1m')
   WHITE = str('\033[37m')
   BLACK = str('\033[30m')
   ON_RED = str('\033[41m')
   MSG = str('\033[37m')
   NAME = str('\033[96m')
   END = str('\033[0m')


CRITICAL        = const(50)
ERROR           = const(40)
WARNING         = const(30)
INFO            = const(20)
DEBUG           = const(10)
DEBUG_EXTENDED  = const(5)
NOTSET          = const(0)

_nocolor_dict = {
    CRITICAL: "CRIT",
    ERROR: "ERROR",
    WARNING: "WARN",
    INFO: "INFO",
    DEBUG: "DEBUG",
    DEBUG_EXTENDED:"DEBUG_EXTENDED",
}

_level_dict = {
    CRITICAL: s.ON_RED+s.BOLD+s.WHITE+"CRIT"+s.END,
    ERROR: s.BOLD+s.RED+"ERROR"+s.END,
    WARNING: s.BOLD+s.YELLOW+"WARN"+s.END,
    INFO: s.BLUE+"INFO"+s.END,
    DEBUG: s.GREEN+"DEBUG"+s.END,
    DEBUG_EXTENDED: s.GREEN+"DEBUG"+s.BLUE+"(EXTENDED)"+s.END,
}

_stream = sys.stderr

class Logger:

    level = NOTSET

    def __init__(self, name, log_time=False):
        self.name = s.NAME+str(name)+s.END
        self.log_time = log_time

    def _level_str(self, level):
        l = _level_dict.get(level)
        if l is not None:
            return l
        return "LVL%s " % level

    def setLevel(self, level):
        self.level = level

    def isEnabledFor(self, level):
        return level >= (self.level or _level)

    def set_timing(self, timing):
        self.log_time = True if timing else False

    def log(self, level, msg, *args):
        if level >= self.level:
            if self.log_time:
                time = clock()
                time = "({}{:02}:{:02}:{:02}{}): ".format(s.MAGENTA,time['hours'],time['minutes'],time['seconds'],s.END)
            else:
                time = " "
            _stream.write("%s:%s:%s" % (self._level_str(level), self.name, time))
            if not isinstance(msg, str):
                msg = str(msg)
            if not args:
                print(s.MSG+msg+s.END, file=_stream)
            else:
                raise(NotImplementedError("Additional Args not handled by Logger yet"))

    def debug(self, msg, *args):
        self.log(DEBUG, msg, *args)

    def debug_ext(self, msg, *args):
        self.log(DEBUG_EXTENDED, msg, *args)

    def info(self, msg, *args):
        self.log(INFO, msg, *args)

    def warning(self, msg, *args):
        self.log(WARNING, msg, *args)

    def error(self, msg, *args):
        self.log(ERROR, msg, *args)

    def critical(self, msg, *args):
        self.log(CRITICAL, msg, *args)

    def exc(self, e, msg, *args):
        self.log(ERROR, msg, *args)
        sys.print_exception(e, _stream)

    def exception(self, msg, *args):
        self.exc("Exception: ", msg, *args)


_level = INFO
_loggers = {}

def getLogger(name, log_time=False):
    if name in _loggers:
        return _loggers[name]
    l = Logger(name, log_time)
    _loggers[name] = l
    return l

def set_all_levels(level):
    global _level
    _level = level
    for logger in _loggers:
        logger.setLevel = level

def info(msg, *args):
    getLogger(None).info(msg, *args)

def debug(msg, *args):
    getLogger(None).debug(msg, *args)

def basicConfig(level=INFO, filename=None, stream=None, format=None, color=False):
    global _level, _stream, _level_dict
    _level = level
    if stream:
        _stream = stream
    if not color:
        _level_dict = _nocolor_dict
        s.NAME, s.MSG = "", ""
    if filename is not None:
        print("logging.basicConfig: filename arg is not supported")
    if format is not None:
        print("logging.basicConfig: format arg is not supported")