# 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/.

import argparse
import optparse
import os
import sys
from collections import defaultdict

from . import handlers
from . import formatters
from .structuredlog import StructuredLogger, set_default_logger

log_formatters = {
    'raw': (formatters.JSONFormatter, "Raw structured log messages"),
    'unittest': (formatters.UnittestFormatter, "Unittest style output"),
    'xunit': (formatters.XUnitFormatter, "xUnit compatible XML"),
    'html': (formatters.HTMLFormatter, "HTML report"),
    'mach': (formatters.MachFormatter, "Human-readable output"),
    'tbpl': (formatters.TbplFormatter, "TBPL style log format"),
    'errorsummary': (formatters.ErrorSummaryFormatter, argparse.SUPPRESS),
}

TEXT_FORMATTERS = ('raw', 'mach')
"""a subset of formatters for non test harnesses related applications"""

def level_filter_wrapper(formatter, level):
    return handlers.LogLevelFilter(formatter, level)

def verbose_wrapper(formatter, verbose):
    formatter.verbose = verbose
    return formatter

def buffer_handler_wrapper(handler, buffer_limit):
    if buffer_limit == "UNLIMITED":
        buffer_limit = None
    else:
        buffer_limit = int(buffer_limit)
    return handlers.BufferHandler(handler, buffer_limit)

def valgrind_handler_wrapper(handler):
    return handlers.ValgrindHandler(handler)

def default_formatter_options(log_type, overrides):
    formatter_option_defaults = {
        "raw": {
            "level": "debug"
        }
    }
    rv = {"verbose": False,
          "level": "info"}
    rv.update(formatter_option_defaults.get(log_type, {}))

    if overrides is not None:
        rv.update(overrides)

    return rv

fmt_options = {
    # <option name>: (<wrapper function>, description, <applicable formatters>, action)
    # "action" is used by the commandline parser in use.
    'verbose': (verbose_wrapper,
                "Enables verbose mode for the given formatter.",
                ["mach"], "store_true"),
    'level': (level_filter_wrapper,
              "A least log level to subscribe to for the given formatter (debug, info, error, etc.)",
              ["mach", "raw", "tbpl"], "store"),
    'buffer': (buffer_handler_wrapper,
               "If specified, enables message buffering at the given buffer size limit.",
               ["mach", "tbpl"], "store"),
}


def log_file(name):
    if name == "-":
        return sys.stdout
    # ensure we have a correct dirpath by using realpath
    dirpath = os.path.dirname(os.path.realpath(name))
    if not os.path.exists(dirpath):
        os.makedirs(dirpath)
    return open(name, "w")


def add_logging_group(parser, include_formatters=None):
    """
    Add logging options to an argparse ArgumentParser or
    optparse OptionParser.

    Each formatter has a corresponding option of the form --log-{name}
    where {name} is the name of the formatter. The option takes a value
    which is either a filename or "-" to indicate stdout.

    :param parser: The ArgumentParser or OptionParser object that should have
                   logging options added.
    :param include_formatters: List of formatter names that should be included
                               in the option group. Default to None, meaning
                               all the formatters are included. A common use
                               of this option is to specify
                               :data:`TEXT_FORMATTERS` to include only the
                               most useful formatters for a command line tool
                               that is not related to test harnesses.
    """
    group_name = "Output Logging"
    group_description = ("Each option represents a possible logging format "
                         "and takes a filename to write that format to, "
                         "or '-' to write to stdout.")

    if include_formatters is None:
        include_formatters = log_formatters.keys()

    if isinstance(parser, optparse.OptionParser):
        group = optparse.OptionGroup(parser,
                                     group_name,
                                     group_description)
        parser.add_option_group(group)
        opt_log_type = 'str'
        group_add = group.add_option
    else:
        group = parser.add_argument_group(group_name,
                                          group_description)
        opt_log_type = log_file
        group_add = group.add_argument

    for name, (cls, help_str) in log_formatters.iteritems():
        if name in include_formatters:
            group_add("--log-" + name, action="append", type=opt_log_type,
                      help=help_str)

    for optname, (cls, help_str, formatters, action) in fmt_options.iteritems():
        for fmt in formatters:
            # make sure fmt is in log_formatters and is accepted
            if fmt in log_formatters and fmt in include_formatters:
                group_add("--log-%s-%s" % (fmt, optname), action=action,
                          help=help_str, default=None)


def setup_handlers(logger, formatters, formatter_options):
    """
    Add handlers to the given logger according to the formatters and
    options provided.

    :param logger: The logger configured by this function.
    :param formatters: A dict of {formatter, [streams]} to use in handlers.
    :param formatter_options: a dict of {formatter: {option: value}} to
                              to use when configuring formatters.
    """
    unused_options = set(formatter_options.keys()) - set(formatters.keys())
    if unused_options:
        msg = ("Options specified for unused formatter(s) (%s) have no effect" %
               list(unused_options))
        raise ValueError(msg)

    for fmt, streams in formatters.iteritems():
        formatter_cls = log_formatters[fmt][0]
        formatter = formatter_cls()
        handler_wrappers_and_options = []

        for option, value in formatter_options[fmt].iteritems():
            wrapper, wrapper_args = None, ()
            if option == "valgrind":
                wrapper = valgrind_handler_wrapper
            elif option == "buffer":
                wrapper, wrapper_args = fmt_options[option][0], (value,)
            else:
                formatter = fmt_options[option][0](formatter, value)

            if wrapper is not None:
                handler_wrappers_and_options.append((wrapper, wrapper_args))

        for value in streams:
            handler = handlers.StreamHandler(stream=value, formatter=formatter)
            for wrapper, wrapper_args in handler_wrappers_and_options:
                handler = wrapper(handler, *wrapper_args)
            logger.add_handler(handler)


def setup_logging(logger, args, defaults=None, formatter_defaults=None):
    """
    Configure a structuredlogger based on command line arguments.

    The created structuredlogger will also be set as the default logger, and
    can be retrieved with :py:func:`~mozlog.get_default_logger`.

    :param logger: A StructuredLogger instance or string name. If a string, a
                   new StructuredLogger instance will be created using
                   `logger` as the name.
    :param args: A dictionary of {argument_name:value} produced from
                 parsing the command line arguments for the application
    :param defaults: A dictionary of {formatter name: output stream} to apply
                     when there is no logging supplied on the command line. If
                     this isn't supplied, reasonable defaults are chosen
                     (coloured mach formatting if stdout is a terminal, or raw
                     logs otherwise).
    :param formatter_defaults: A dictionary of {option_name: default_value} to provide
                               to the formatters in the absence of command line overrides.
    :rtype: StructuredLogger
    """

    if not isinstance(logger, StructuredLogger):
        logger = StructuredLogger(logger)

    # Keep track of any options passed for formatters.
    formatter_options = {}
    # Keep track of formatters and list of streams specified.
    formatters = defaultdict(list)
    found = False
    found_stdout_logger = False
    if args is None:
        args = {}
    if not hasattr(args, 'iteritems'):
        args = vars(args)

    if defaults is None:
        if sys.__stdout__.isatty():
            defaults = {"mach": sys.stdout}
        else:
            defaults = {"raw": sys.stdout}

    for name, values in args.iteritems():
        parts = name.split('_')
        if len(parts) > 3:
            continue
        # Our args will be ['log', <formatter>]
        #               or ['log', <formatter>, <option>]
        #               or ['valgrind']
        if parts[0] == 'log' and values is not None:
            if len(parts) == 1 or parts[1] not in log_formatters:
                continue
            if len(parts) == 2:
                _, formatter = parts
                for value in values:
                    found = True
                    if isinstance(value, basestring):
                        value = log_file(value)
                    if value == sys.stdout:
                        found_stdout_logger = True
                    formatters[formatter].append(value)
            if len(parts) == 3:
                _, formatter, opt = parts
                if formatter not in formatter_options:
                    formatter_options[formatter] = default_formatter_options(formatter,
                                                                             formatter_defaults)
                formatter_options[formatter][opt] = values

    #If there is no user-specified logging, go with the default options
    if not found:
        for name, value in defaults.iteritems():
            formatters[name].append(value)

    elif not found_stdout_logger and sys.stdout in defaults.values():
        for name, value in defaults.iteritems():
            if value == sys.stdout:
                formatters[name].append(value)

    for name in formatters:
        if name not in formatter_options:
            formatter_options[name] = default_formatter_options(name, formatter_defaults)

    # If the user specified --valgrind, add it as an option for all formatters
    if args.get('valgrind', None) is not None:
        for name in formatters:
            formatter_options[name]['valgrind'] = True
    setup_handlers(logger, formatters, formatter_options)
    set_default_logger(logger)

    return logger
