#
# This file is part of pysmi software.
#
# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>
# License: https://www.pysnmp.com/pysmi/license.html
#
import logging
from pysmi import error
from pysmi import __version__

flagNone = 0x0000
flagSearcher = 0x0001
flagReader = 0x0002
flagLexer = 0x0004
flagParser = 0x0008
flagGrammar = 0x0010
flagCodegen = 0x0020
flagWriter = 0x0040
flagCompiler = 0x0080
flagBorrower = 0x0100
flagAll = 0xFFFF

flagMap = {
    "searcher": flagSearcher,
    "reader": flagReader,
    "lexer": flagLexer,
    "parser": flagParser,
    "grammar": flagGrammar,
    "codegen": flagCodegen,
    "writer": flagWriter,
    "compiler": flagCompiler,
    "borrower": flagBorrower,
    "all": flagAll,
}


class Printer:
    def __init__(self, logger=None, handler=None, formatter=None):
        if logger is None:
            logger = logging.getLogger("pysmi")

        logger.setLevel(logging.DEBUG)

        if handler is None:
            handler = logging.StreamHandler()

        if formatter is None:
            formatter = logging.Formatter("%(asctime)s %(name)s: %(message)s")

        handler.setFormatter(formatter)
        handler.setLevel(logging.DEBUG)

        logger.addHandler(handler)

        self.__logger = logger

    def __call__(self, msg):
        self.__logger.debug(msg)

    def __str__(self):
        return "<python built-in logging>"

    def getCurrentLogger(self):
        return self.__logger


if hasattr(logging, "NullHandler"):
    NullHandler = logging.NullHandler
else:
    # Python 2.6 and older
    class NullHandler(logging.Handler):
        def emit(self, record):
            pass


class Debug:
    defaultPrinter = None

    def __init__(self, *flags, **options):
        self._flags = flagNone
        if options.get("printer") is not None:
            self._printer = options.get("printer")

        elif self.defaultPrinter is not None:
            self._printer = self.defaultPrinter

        else:
            if "loggerName" in options:
                # route our logs to parent logger
                self._printer = Printer(
                    logger=logging.getLogger(options["loggerName"]),
                    handler=NullHandler(),
                )
            else:
                self._printer = Printer()

        self(f"running pysmi version {__version__}")

        for flag in flags:
            inverse = flag and flag[0] in ("!", "~")

            if inverse:
                flag = flag[1:]

            try:
                if inverse:
                    self._flags &= ~flagMap[flag]
                else:
                    self._flags |= flagMap[flag]

            except KeyError:
                raise error.PySmiError(f"bad debug flag {flag}")

            self(f"debug category '{flag}' {'disabled' if inverse else 'enabled'}")

    def __str__(self):
        return f"logger {self._printer}, flags {self._flags:x}"

    def __call__(self, msg):
        self._printer(msg)

    def __and__(self, flag):
        return self._flags & flag

    def __rand__(self, flag):
        return flag & self._flags

    def getCurrentPrinter(self):
        return self._printer

    def getCurrentLogger(self):
        return self._printer and self._printer.getCurrentLogger() or None


# This will yield false from bitwise and with a flag, and save
# on unnecessary calls
logger = 0


def setLogger(l):
    global logger
    logger = l
