# Copyright 2015 Canonical Ltd.
# This file is part of cloud-init.  See LICENCE file for license information.
#
# vi: ts=4 expandtab

import logging
import sys

try:
    from unittest import mock
except ImportError:
    import mock  # noqa


_IS_PY26 = sys.version_info[0:2] == (2, 6)


# This is similar with unittest.TestCase.assertLogs from Python 3.4.
class SnatchHandler(logging.Handler):

    if _IS_PY26:
        # Old style junk is required on 2.6...
        def __init__(self, *args, **kwargs):
            logging.Handler.__init__(self, *args, **kwargs)
            self.output = []
    else:
        def __init__(self, *args, **kwargs):
            super(SnatchHandler, self).__init__(*args, **kwargs)
            self.output = []

    def emit(self, record):
        msg = self.format(record)
        self.output.append(msg)


class LogSnatcher(object):
    """A context manager to capture emitted logged messages.

    The class can be used as following::

        with LogSnatcher('plugins.windows.createuser') as snatcher:
            LOG.info("doing stuff")
            LOG.info("doing stuff %s", 1)
            LOG.warn("doing other stuff")
            ...
        self.assertEqual(snatcher.output,
                         ['INFO:unknown:doing stuff',
                          'INFO:unknown:doing stuff 1',
                          'WARN:unknown:doing other stuff'])
    """

    @property
    def output(self):
        """Get the output of this Snatcher.

        The output is a list of log messages, already formatted.
        """
        return self._snatch_handler.output

    def __init__(self, logger_name):
        self._logger_name = logger_name
        self._snatch_handler = SnatchHandler()
        self._logger = logging.getLogger(self._logger_name)
        self._previous_level = self._logger.getEffectiveLevel()

    def __enter__(self):
        self._logger.setLevel(logging.DEBUG)
        self._logger.handlers.append(self._snatch_handler)
        return self

    def __exit__(self, *args):
        self._logger.handlers.remove(self._snatch_handler)
        self._logger.setLevel(self._previous_level)