# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

# This file contains logging functionality for mach. It essentially provides
# support for a structured logging framework built on top of Python's built-in
# logging framework.

from __future__ import absolute_import, unicode_literals

try:
    import blessings
except ImportError:
    blessings = None

import json
import logging
import sys
import time


def format_seconds(total):
    """Format number of seconds to MM:SS.DD form."""

    minutes, seconds = divmod(total, 60)

    return '%2d:%05.2f' % (minutes, seconds)


class ConvertToStructuredFilter(logging.Filter):
    """Filter that converts unstructured records into structured ones."""
    def filter(self, record):
        if hasattr(record, 'action') and hasattr(record, 'params'):
            return True

        record.action = 'unstructured'
        record.params = {'msg': record.getMessage()}
        record.msg = '{msg}'

        return True


class StructuredJSONFormatter(logging.Formatter):
    """Log formatter that writes a structured JSON entry."""

    def format(self, record):
        action = getattr(record, 'action', 'UNKNOWN')
        params = getattr(record, 'params', {})

        return json.dumps([record.created, action, params])


class StructuredHumanFormatter(logging.Formatter):
    """Log formatter that writes structured messages for humans.

    It is important that this formatter never be added to a logger that
    produces unstructured/classic log messages. If it is, the call to format()
    could fail because the string could contain things (like JSON) that look
    like formatting character sequences.

    Because of this limitation, format() will fail with a KeyError if an
    unstructured record is passed or if the structured message is malformed.
    """
    def __init__(self, start_time, write_interval=False, write_times=True):
        self.start_time = start_time
        self.write_interval = write_interval
        self.write_times = write_times
        self.last_time = None

    def format(self, record):
        if not self.write_times:
            return record.msg.format(**record.params)

        elapsed = self._time(record)

        return '%s %s' % (format_seconds(elapsed),
            record.msg.format(**record.params))

    def _time(self, record):
        t = record.created - self.start_time

        if self.write_interval and self.last_time is not None:
            t = record.created - self.last_time

        self.last_time = record.created

        return t


class StructuredTerminalFormatter(StructuredHumanFormatter):
    """Log formatter for structured messages writing to a terminal."""

    def set_terminal(self, terminal):
        self.terminal = terminal

    def format(self, record):
        t = self.terminal.blue(format_seconds(self._time(record)))
        f = record.msg.format(**record.params)

        return '%s %s' % (t, self._colorize(f))

    def _colorize(self, s):
        if not self.terminal:
            return s

        result = s

        if s.startswith('TEST-PASS'):
            result = self.terminal.green(s[0:9]) + s[9:]
        elif s.startswith('TEST-UNEXPECTED'):
            result = self.terminal.red(s[0:20]) + s[20:]

        return result


class LoggingManager(object):
    """Holds and controls global logging state.

    An application should instantiate one of these and configure it as needed.

    This class provides a mechanism to configure the output of logging data
    both from mach and from the overall logging system (e.g. from other
    modules).
    """

    def __init__(self):
        self.start_time = time.time()

        self.json_handlers = []
        self.terminal_handler = None
        self.terminal_formatter = None

        self.root_logger = logging.getLogger()
        self.root_logger.setLevel(logging.DEBUG)

        # Installing NullHandler on the root logger ensures that *all* log
        # messages have at least one handler. This prevents Python from
        # complaining about "no handlers could be found for logger XXX."
        self.root_logger.addHandler(logging.NullHandler())

        self.mach_logger = logging.getLogger('mach')
        self.mach_logger.setLevel(logging.DEBUG)

        self.structured_filter = ConvertToStructuredFilter()

        self.structured_loggers = [self.mach_logger]

        self._terminal = None

    @property
    def terminal(self):
        if not self._terminal and blessings:
            # Sometimes blessings fails to set up the terminal. In that case,
            # silently fail.
            try:
                terminal = blessings.Terminal(stream=sys.stdout)

                if terminal.is_a_tty:
                    self._terminal = terminal
            except Exception:
                pass

        return self._terminal

    def add_json_handler(self, fh):
        """Enable JSON logging on the specified file object."""

        # Configure the consumer of structured messages.
        handler = logging.StreamHandler(stream=fh)
        handler.setFormatter(StructuredJSONFormatter())
        handler.setLevel(logging.DEBUG)

        # And hook it up.
        for logger in self.structured_loggers:
            logger.addHandler(handler)

        self.json_handlers.append(handler)

    def add_terminal_logging(self, fh=sys.stdout, level=logging.INFO,
            write_interval=False):
        """Enable logging to the terminal."""

        formatter = StructuredHumanFormatter(self.start_time,
            write_interval=write_interval)

        if self.terminal:
            formatter = StructuredTerminalFormatter(self.start_time,
                write_interval=write_interval)
            formatter.set_terminal(self.terminal)

        handler = logging.StreamHandler(stream=fh)
        handler.setFormatter(formatter)
        handler.setLevel(level)

        for logger in self.structured_loggers:
            logger.addHandler(handler)

        self.terminal_handler = handler
        self.terminal_formatter = formatter

    def replace_terminal_handler(self, handler):
        """Replace the installed terminal handler.

        Returns the old handler or None if none was configured.
        If the new handler is None, removes any existing handler and disables
        logging to the terminal.
        """
        old = self.terminal_handler

        if old:
            for logger in self.structured_loggers:
                logger.removeHandler(old)

        if handler:
            for logger in self.structured_loggers:
                logger.addHandler(handler)

        self.terminal_handler = handler

        return old

    def enable_unstructured(self):
        """Enable logging of unstructured messages."""
        if self.terminal_handler:
            self.terminal_handler.addFilter(self.structured_filter)
            self.root_logger.addHandler(self.terminal_handler)

    def disable_unstructured(self):
        """Disable logging of unstructured messages."""
        if self.terminal_handler:
            self.terminal_handler.removeFilter(self.structured_filter)
            self.root_logger.removeHandler(self.terminal_handler)

    def register_structured_logger(self, logger):
        """Register a structured logger.

        This needs to be called for all structured loggers that don't chain up
        to the mach logger in order for their output to be captured.
        """
        self.structured_loggers.append(logger)
