"""
This module contains tools to log data from runs.
Unlike a conventional python process, processes run by asimov may wish to send information to a number of different locations, and store
information for review purposes.
"""

import logging
import os

from asimov import mattermost

from asimov import config
#from .gitlab import EventIssue

import asimov.database as database

logging.getLogger("werkzeug").setLevel(logging.WARNING)
logging.getLogger("MARKDOWN").setLevel(logging.WARNING)

class AsimovLogger():

    def __init__(self, logfile):
        """
        An object for logging asimov productions.

        Parameters
        ----------
        logfile : str
           The location of the log file to be written.
        """
        self.logfile = logfile
        self.mattermost = mattermost.Mattermost()
        self.file_logger = logging.basicConfig(filename=logfile, level=logging.DEBUG)
        
    def log(self, level, message, event=None, production=None, pipeline=None, module=None, time=None):
        """
        Record a log message.

        Parameters
        ----------
        level : str, {DEBUG, INFO, WARNING, ERROR}
           The level of the logging message.
        event : ``asimov.event.Event``
           The event which this message is for.
        production : ``asimov.event.Production``, optional
           The production this message is for.
        message : str
           The free-form message for the log message.
        channels : list, or str, {"file", "mattermost", "gitlab"}, optional
           The list of places where the log message should be sent.
           Defaults to file only.
        """

        logger_levels = {"debug": logging.DEBUG,
                         "info": logging.INFO,
                         "warning": logging.WARNING,
                         "error": logging.ERROR,
                         "update": 9}

        if not production:
            production = ""

        logging.log(logger_levels[level.lower()],
                    message)
            
        
    def info(self, message, production=None, channels="file"):
        """
        Record an information message.

        Parameters
        ----------

        production : ``asimov.event.Production``, optional
           The production this message is for.
        message : str
           The free-form message for the log message.
        channels : list, or str, {"file", "mattermost", "gitlab"}, optional
           The list of places where the log message should be sent.
           Defaults to file only.
        """

        self.log("info", message, production, channels)

    def error(self, message, production=None, channels="file"):
        """
        Record an error message.

        Parameters
        ----------

        production : ``asimov.event.Production``, optional
           The production this message is for.
        message : str
           The free-form message for the log message.
        channels : list, or str, {"file", "mattermost", "gitlab"}, optional
           The list of places where the log message should be sent.
           Defaults to file only.
        """

        self.log("error", message, production, channels)

    def warning(self, message, production=None, channels="file"):
        """
        Record an warning message.

        Parameters
        ----------

        production : ``asimov.event.Production``, optional
           The production this message is for.
        message : str
           The free-form message for the log message.
        channels : list, or str, {"file", "mattermost", "gitlab"}, optional
           The list of places where the log message should be sent.
           Defaults to file only.
        """

        self.log("warning", message, production, channels)

    def list(self, offset=0, length=10, **filters):

        class LogEntry:
            def __init__(self, data):
                data = data.strip().split(":")
                self.level = data[0].lower()
                try:
                    self.module = data[1]
                    if self.module == "root":
                        self.module = "asimov"
                except:
                    self.module = None
                try:
                    self.message = data[2]
                except:
                    self.message = None
            def __dictrepr__(self):
                return dict(level=self.level, module=self.module, message=self.message)

        entries = []
        with open(self.logfile, "r") as filehandle:
            for line in filehandle:
                entries.append(LogEntry(line))


        def apply_filter(entries, parameter, value):
            entries = filter(lambda x: getattr(x, parameter) == value,
                             entries)
            return entries

        if filters:
            for parameter, value in filters.items():
                entries = apply_filter(entries, parameter, value)
            entries = list(entries)

                
        if offset:
            return entries[-int(length)+int(offset):-int(offset)]
        else:
            return entries[-int(length):]


class DatabaseLogger(AsimovLogger):
    """
    This class implements a database-backed log collector.
    """

    def __init__(self):
        self.database = database.Logger
    

    def log(cls, level, message, event=None, production=None, pipeline=None, module=None):
        """
        Record a log message.

        Parameters
        ----------
        level : str, {DEBUG, INFO, WARNING, ERROR}
           The level of the logging message.
        production : ``asimov.event.Production``, optional
           The production this message is for.
        message : str
           The free-form message for the log message.
        channels : list, or str, {"file", "mattermost", "gitlab"}, optional
           The list of places where the log message should be sent.
           Defaults to file only.
        """

        logger_levels = {"debug": logging.DEBUG,
                         "info": logging.INFO,
                         "warning": logging.WARNING,
                         "error": logging.ERROR}
        entry = self.database(pipeline,
                              module,
                              level,
                              datetime.datetime.now(),
                              event,
                              production,
                              message)
        entry.save()

    def list(self, **filters):
        """
        Return all logging events which satisfy a set of ``filters``.

        Examples
        --------
        
        """

        events = self.database.list(**filters)
