# 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 sys
from contextlib import contextmanager


class ErrorMessage(Exception):
    '''Exception type raised from errors.error() and errors.fatal()'''


class AccumulatedErrors(Exception):
    '''Exception type raised from errors.accumulate()'''


class ErrorCollector(object):
    '''
    Error handling/logging class. A global instance, errors, is provided for
    convenience.

    Warnings, errors and fatal errors may be logged by calls to the following
    functions:
        errors.warn(message)
        errors.error(message)
        errors.fatal(message)

    Warnings only send the message on the logging output, while errors and
    fatal errors send the message and throw an ErrorMessage exception. The
    exception, however, may be deferred. See further below.

    Errors may be ignored by calling:
        errors.ignore_errors()

    After calling that function, only fatal errors throw an exception.

    The warnings, errors or fatal errors messages may be augmented with context
    information when a context is provided. Context is defined by a pair
    (filename, linenumber), and may be set with errors.context() used as a
    context manager:
        with errors.context(filename, linenumber):
            errors.warn(message)

    Arbitrary nesting is supported, both for errors.context calls:
        with errors.context(filename1, linenumber1):
            errors.warn(message)
            with errors.context(filename2, linenumber2):
                errors.warn(message)

    as well as for function calls:
        def func():
            errors.warn(message)
        with errors.context(filename, linenumber):
            func()

    Errors and fatal errors can have their exception thrown at a later time,
    allowing for several different errors to be reported at once before
    throwing. This is achieved with errors.accumulate() as a context manager:
        with errors.accumulate():
            if test1:
                errors.error(message1)
            if test2:
                errors.error(message2)

    In such cases, a single AccumulatedErrors exception is thrown, but doesn't
    contain information about the exceptions. The logged messages do.
    '''
    out = sys.stderr
    WARN = 1
    ERROR = 2
    FATAL = 3
    _level = ERROR
    _context = []
    _count = None

    def ignore_errors(self, ignore=True):
        if ignore:
            self._level = self.FATAL
        else:
            self._level = self.ERROR

    def _full_message(self, level, msg):
        if level >= self._level:
            level = 'Error'
        else:
            level = 'Warning'
        if self._context:
            file, line = self._context[-1]
            return "%s: %s:%d: %s" % (level, file, line, msg)
        return "%s: %s" % (level, msg)

    def _handle(self, level, msg):
        msg = self._full_message(level, msg)
        if level >= self._level:
            if self._count is None:
                raise ErrorMessage(msg)
            self._count += 1
        print >>self.out, msg

    def fatal(self, msg):
        self._handle(self.FATAL, msg)

    def error(self, msg):
        self._handle(self.ERROR, msg)

    def warn(self, msg):
        self._handle(self.WARN, msg)

    def get_context(self):
        if self._context:
            return self._context[-1]

    @contextmanager
    def context(self, file, line):
        if file and line:
            self._context.append((file, line))
        yield
        if file and line:
            self._context.pop()

    @contextmanager
    def accumulate(self):
        assert self._count is None
        self._count = 0
        yield
        count = self._count
        self._count = None
        if count:
            raise AccumulatedErrors()

    @property
    def count(self):
        # _count can be None.
        return self._count if self._count else 0


errors = ErrorCollector()
