# Copyright 2015 VMware, Inc.  All rights reserved. -- VMware Confidential
#
'''Holder of some handy functions for setting up a logging
'''
import os
import time
import logging
from logging import StreamHandler
from logging.handlers import WatchedFileHandler

# Default value for logger formatter `datefmt` argument
_LOGGING_DATEFMT = "%Y-%m-%dT%H:%M:%S"

# Default value for logger formatter `fmt` argument
_LOGGING_FMT = "%(asctime)s.%(msecs)dZ %(levelname)s %(name)s %(message)s"

# Global minimal logging level (local level may be decreasing)
_LOGGING_LEVEL = logging.INFO


def decodeLoggingLevel(levelName, default=_LOGGING_LEVEL):
    ''' Decode string level name to its integer value

    @param levelName: name of logging level (like "INFO")
    @type levelName: str
    @param default: default value when levelName is not recognized
    @type default: int
    @return: integer value of this named level
    @rtype: int
    '''
    return getattr(logging, levelName.upper(), default) if levelName else default

def getApplicationLoggingLevel(level):
    ''' Returns application logging level: minimal value from custom `level`,
    _LOGGING_LEVEL and environment `VMWARE_UR_LOGLEVEL` variable, so
    there are 3 ways to decrease logging level for all loggers

    @param level: custom logging level
    @type level: int
    @return: Effective logging severity for all application loggers
    @rtype: int
    '''
    return decodeLoggingLevel(os.getenv("VMWARE_UR_LOGLEVEL"), level)

def getLogger(name=None, level=_LOGGING_LEVEL):
    ''' The same as logging.getLogger() but with additional arg `level`

    @param name: name of the logger
    @type name: str
    @param level: severity level
    @type: int
    @return: default logger for UpgradeRunner with already configured level
    @rtype: logging.RootLogger
    '''
    logger = logging.getLogger(name)
    logger.setLevel(getApplicationLoggingLevel(level))
    return logger

class Formatter(logging.Formatter):
    ''' Default Formatter for UpgradeRunner
    '''
    def __init__(self, fmt=_LOGGING_FMT, datefmt=_LOGGING_DATEFMT):
        logging.Formatter.__init__(self, fmt, datefmt)
        self.converter = time.gmtime

def basicConfig(**kwargs):
    ''' Default logging configuration for UpgradeRunner

    @param kwargs: the same as in logging.basicConfig()
    @type kwargs: dict
    '''
    logging.Formatter.converter = time.gmtime
    kwargs.setdefault("format", _LOGGING_FMT)
    kwargs.setdefault("datefmt", _LOGGING_DATEFMT)
    kwargs["level"] = getApplicationLoggingLevel(
            kwargs.get("level", _LOGGING_LEVEL))
    logging.basicConfig(**kwargs)

def addFilter(messageText):
    '''Adds filter into all log handlers.

    @param messageText: The text which need to be filtered in log records
    '''
    class FilterAggregatorWarningMessage(logging.Filter):
        def filter(self, record):
            return messageText not in record.getMessage()

    for hdl in logging.getLogger(None).handlers:
        hdl.addFilter(FilterAggregatorWarningMessage())

    logging.getLogger(None).addFilter(FilterAggregatorWarningMessage())

def setupLogging(filePath, level, logOnScreen):
    '''Setup logging to print all log messages with level greater than given
    level.
    '''
    root = getLogger('', level)
    formatter = Formatter()

    if filePath:
        # Log in a file
        handler = WatchedFileHandler(filePath)
        handler.setFormatter(formatter)
        root.addHandler(handler)
    if logOnScreen:
        handler = StreamHandler()
        handler.setFormatter(formatter)
        root.addHandler(handler)
