'''
A basic class for handling the log files generated by larpix-scripts
Typical usage:
``
sl = ScriptLogger()
log = ScriptLogger.get_script_log()
log.info(<message>) # print something to script log + stdout
sl.flush_datalog() # store current serial data to file
``
The script log can be accessed from any module via
``
from helpers.script_logging import ScriptLogger
log = ScriptLogger.get_script_log()
``
'''

import logging
import time
import sys
import os
import larpix.larpix as larpix
import helpers.pathnames as pathnames

class ScriptLogger(object):
    script_logging_format = '%(asctime)s %(levelname)s: %(message)s'
    script_log_level = logging.DEBUG

    def __init__(self, start_time=None, script_logfile=None, data_logfile=None):
        if start_time is None:
            self.start_time = time.time()
        else:
            self.start_time = start_time
        if script_logfile is None:
            self.script_logdir = pathnames.default_script_logdir(self.start_time)
            self.script_logfile = pathnames.default_script_logfile(self.start_time)
        else:
            self.script_logdir = os.path.split(script_logfile)[0]
            self.script_logfile = script_logfile
        if data_logfile is None:
            self.data_logdir = pathnames.default_data_logdir(self.start_time)
            self.data_logfile = pathnames.default_data_logfile(self.start_time)
        else:
            self.data_logdir = os.path.split(data_logfile)[0]
            self.data_logfile = data_logfile

        self.init_script_logging()
        self.script_log.info('initalized script logger')
        self.script_log.info('logging to %s' % self.script_logfile)

        self.init_data_logging()
        self.script_log.info('initialized data logger')
        self.script_log.info('storing data to %s' % self.data_logfile)

    def init_script_logging(self):
        self.script_log = self.get_script_log()
        pathnames.mkdir_p(self.script_logdir)
        self.script_log_fhandler = logging.FileHandler(self.script_logfile)
        self.script_log_shandler = ScriptLogger.init_stream_handler()
        self.script_log_formatter = \
            logging.Formatter(fmt=self.script_logging_format)
        self.script_log_fhandler.setFormatter(self.script_log_formatter)
        self.script_log_shandler.setFormatter(self.script_log_formatter)
        self.script_log.addHandler(self.script_log_fhandler)
        self.script_log.addHandler(self.script_log_shandler)
        self.script_log.setLevel(self.script_log_level)

    def init_data_logging(self):
        self.enable_datalog(self.data_logfile)

    @classmethod
    def init_stream_handler(cls):
        ''' Creates stream handler if it does not exist '''
        logger = logging.getLogger(pathnames.script_name)
        shandler = None
        if not any([isinstance(handler, logging.StreamHandler)
                    for handler in logger.handlers]):
            shandler = logger.addHandler(logging.StreamHandler(sys.stdout))
        else:
            shandler = [handler for handler in logger.handlers
                        if isinstance(handler, logging.StreamHandler)][0]
        return shandler

    @classmethod
    def get_script_log(cls):
        '''
        Gives access to script logger, if no ScriptLogger object has been created
        only the stdout StreamHandler is initialized
        Thus a print statement can be replaced with logger.info(<output>)
        '''
        cls.init_stream_handler()
        return logging.getLogger(pathnames.script_name)

    def enable_datalog(self, filename=None):
        if not filename is None:
            self.data_logdir = os.path.split(filename)[0]
            self.data_logfile = filename
        return larpix.enable_logger(self.data_logfile)

    def flush_datalog(self):
        return larpix.flush_logger()

    def disable_datalog(self):
        return larpix.disable_logger()
