#!/usr/bin/python3

import logging
import logging.handlers
import sys
import traceback

from config import Config


class LevelTagFilter(logging.Filter):
    """Add leveltag"""

    def filter(self, record: logging.LogRecord):
        # Extract the first character of the level name
        record.leveltag = record.levelname[0]

        # We never actually filter messages out, just abuse filtering to add an
        # extra field to the LogRecord
        return True


class DebugStdoutFilter(logging.Filter):
    """Filter debug messages sent to stdout"""

    def filter(self, record: logging.LogRecord):
        if record.levelno != logging.DEBUG:
            return True
        if record.module in Config.DEBUG_MODULES:
            return True
        if record.funcName in Config.DEBUG_FUNCTIONS:
            return True
        return False


log = logging.getLogger(Config.LOG_NAME)
log.setLevel(logging.DEBUG)

# stderr
stderr = logging.StreamHandler()
stderr.setLevel(Config.LOG_LEVEL_STDERR)

# syslog
syslog = logging.handlers.SysLogHandler(address='/dev/log')
syslog.setLevel(Config.LOG_LEVEL_SYSLOG)

# Filter
local_filter = LevelTagFilter()
debug_filter = DebugStdoutFilter()

syslog.addFilter(local_filter)

stderr.addFilter(local_filter)
stderr.addFilter(debug_filter)

# create formatter and add it to the handlers
stderr_fmt = logging.Formatter('[%(asctime)s] %(leveltag)s: %(message)s',
                               datefmt='%H:%M:%S')
syslog_fmt = logging.Formatter(
    '[%(name)s] %(module)s.%(funcName)s - %(leveltag)s: %(message)s'
)
stderr.setFormatter(stderr_fmt)
syslog.setFormatter(syslog_fmt)

# add the handlers to the log
log.addHandler(stderr)
log.addHandler(syslog)


def log_uncaught_exceptions(ex_cls, ex, tb):

    print("\033[1;31;47m")
    logging.critical(''.join(traceback.format_tb(tb)))
    print("\033[1;37;40m")
    logging.critical('{0}: {1}'.format(ex_cls, ex))


sys.excepthook = log_uncaught_exceptions
