import logging, os, sys, time

# set up a simple catchall configuration for use during import time.  some code
# may log messages at import time and we don't want those to get completely
# thrown away.  we'll clear this out when actual configuration takes place.
logging.basicConfig(level=logging.DEBUG)

class AllowBelowSeverity(logging.Filter):
    """
    Allows only records less severe than a given level (the opposite of what
    the normal logging level filtering does.
    """
    def __init__(self, level):
        self.level = level


    def filter(self, record):
        return record.levelno < self.level


class LoggingConfig(object):
    global_level = logging.DEBUG
    stdout_level = logging.INFO
    stderr_level = logging.ERROR

    file_formatter = logging.Formatter(
        fmt='%(asctime)s.%(msecs)d %(levelname)-5.5s|%(module)10.10s:'
            '%(lineno)4.4d| %(message)s',
        datefmt='%m/%d %H:%M:%S')

    console_formatter = logging.Formatter(
        fmt='%(asctime)s %(levelname)-5.5s| %(message)s',
        datefmt='%H:%M:%S')

    def __init__(self, use_console=True):
        self.logger = logging.getLogger()
        self.global_level = logging.DEBUG
        self.use_console = use_console


    @classmethod
    def get_timestamped_log_name(cls, base_name):
        return '%s.log.%s' % (base_name, time.strftime('%Y-%m-%d-%H.%M.%S'))


    @classmethod
    def get_autotest_root(cls):
        common_lib_dir = os.path.dirname(__file__)
        return os.path.abspath(os.path.join(common_lib_dir, '..', '..'))


    @classmethod
    def get_server_log_dir(cls):
        return os.path.join(cls.get_autotest_root(), 'logs')


    def add_stream_handler(self, stream, level=logging.DEBUG):
        handler = logging.StreamHandler(stream)
        handler.setLevel(level)
        handler.setFormatter(self.console_formatter)
        self.logger.addHandler(handler)
        return handler


    def add_console_handlers(self):
        stdout_handler = self.add_stream_handler(sys.stdout,
                                                 level=self.stdout_level)
        # only pass records *below* STDERR_LEVEL to stdout, to avoid duplication
        stdout_handler.addFilter(AllowBelowSeverity(self.stderr_level))

        self.add_stream_handler(sys.stderr, self.stderr_level)


    def add_file_handler(self, file_path, level=logging.DEBUG, log_dir=None):
        if log_dir:
            file_path = os.path.join(log_dir, file_path)
        handler = logging.FileHandler(file_path)
        handler.setLevel(level)
        handler.setFormatter(self.file_formatter)
        self.logger.addHandler(handler)
        return handler


    def _add_file_handlers_for_all_levels(self, log_dir, log_name):
        for level in (logging.DEBUG, logging.INFO, logging.WARNING,
                      logging.ERROR):
            file_name = '%s.%s' % (log_name, logging.getLevelName(level))
            self.add_file_handler(file_name, level=level, log_dir=log_dir)


    def add_debug_file_handlers(self, log_dir, log_name=None):
        raise NotImplementedError


    def _clear_all_handlers(self):
        for handler in list(self.logger.handlers):
            self.logger.removeHandler(handler)
            # Attempt to close the handler. If it's already closed a KeyError
            # will be generated. http://bugs.python.org/issue8581
            try:
                handler.close()
            except KeyError:
                pass


    def configure_logging(self, use_console=True, verbose=False):
        self._clear_all_handlers() # see comment at top of file
        self.logger.setLevel(self.global_level)

        if verbose:
            self.stdout_level = logging.DEBUG
        if use_console:
            self.add_console_handlers()


class TestingConfig(LoggingConfig):
    def add_stream_handler(self, *args, **kwargs):
        pass


    def add_file_handler(self, *args, **kwargs):
        pass


    def configure_logging(self, **kwargs):
        pass
