"""
Qxf2 Services: A plug-n-play class for logging.
This class wraps around Python's loguru module.
"""
import os, inspect
import pytest,logging
from loguru import logger
from pytest_reportportal import RPLogger, RPLogHandler

class Base_Logging():
    "A plug-n-play class for logging"
    def __init__(self,log_file_name=None,level="DEBUG",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module} | {message}"):
        "Constructor for the logging class"
        self.log_file_name=log_file_name
        self.log_file_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','log'))
        self.level=level
        self.format=format
        self.log = self.set_log(self.log_file_name,self.level,self.format)


    def set_log(self,log_file_name,level,format,test_module_name=None):
        "Add an handler sending log messages to a sink"
        if test_module_name is None:
            test_module_name = self.get_calling_module()
        if not os.path.exists(self.log_file_dir):
            os.makedirs(self.log_file_dir)
        if log_file_name is None:
            log_file_name = self.log_file_dir + os.sep + test_module_name + '.log'
        else:
            log_file_name = self.log_file_dir + os.sep + log_file_name

        logger.add(log_file_name,level=level,format=format,
        rotation="30 days", filter=None, colorize=None, serialize=False, backtrace=True, enqueue=False, catch=True)


    def get_calling_module(self):
        "Get the name of the calling module"
        calling_file = inspect.stack()[-1][1]
        if 'runpy' in calling_file:
            calling_file = inspect.stack()[4][1]

        calling_filename = calling_file.split(os.sep)

        #This logic bought to you by windows + cygwin + git bash
        if len(calling_filename) == 1: #Needed for
            calling_filename = calling_file.split('/')

        self.calling_module = calling_filename[-1].split('.')[0]

        return self.calling_module


    def setup_rp_logging(self):
        "Setup reportportal logging"
        try:
            # Setting up a logging.
            logging.setLoggerClass(RPLogger)
            rp_logger = logging.getLogger(__name__)
            rp_logger.setLevel(logging.INFO)
            # Create handler for Report Portal.
            rp_handler = RPLogHandler(pytest.config._config.py_test_service)
            # Set INFO level for Report Portal handler.
            rp_handler.setLevel(logging.INFO)
            return rp_logger
        except Exception as e:
            self.write("Exception when trying to set rplogger")
            self.write(str(e))
            self.exceptions.append("Error when setting up the reportportal logger")


    def write(self,msg,level='info'):
        "Write out a message"
        #fname = inspect.stack()[2][3] #May be use a entry-exit decorator instead
        all_stack_frames = inspect.stack()
        for stack_frame in all_stack_frames[1:]:
            if 'Base_Page' not in stack_frame[1]:
                break
        fname = stack_frame[3]
        d = {'caller_func': fname}
        if hasattr(pytest,'config'):
            if pytest.config._config.getoption('--reportportal'):
                rp_logger = self.setup_rp_logging()
                if level.lower()== 'debug':
                    rp_logger.debug(msg=msg)
                elif level.lower()== 'info':
                    rp_logger.info(msg)
                elif level.lower()== 'warn' or level.lower()=='warning':
                    rp_logger.warning(msg)
                elif level.lower()== 'error':
                    rp_logger.error(msg)
                elif level.lower()== 'critical':
                    rp_logger.critical(msg)
                else:
                    rp_logger.critical(msg)
                return

        if level.lower()== 'debug':
            logger.debug("{module} | {msg}",module=d['caller_func'],msg=msg)
        elif level.lower()== 'info':
            logger.info("{module} | {msg}",module=d['caller_func'],msg=msg)
        elif level.lower()== 'warn' or level.lower()=='warning':
            logger.warning("{module} | {msg}",module=d['caller_func'],msg=msg)
        elif level.lower()== 'error':
            logger.error("{module} | {msg}",module=d['caller_func'],msg=msg)
        elif level.lower()== 'critical':
            logger.critical("{module} | {msg}",module=d['caller_func'],msg=msg)
        else:
            logger.critical("Unknown level passed for the msg: {}", msg)