from __future__ import absolute_import

import logging
import sys

from mock import patch

from .. import log
from .utils import TestCase
from .utils import Mock


class test_NullHandler(TestCase):

    def test_emit(self):
        h = log.NullHandler()
        h.emit("record")


class test_get_logger(TestCase):

    def test_when_string(self):
        l = log.get_logger("foo")

        self.assertIs(l, logging.getLogger("foo"))
        h1 = l.handlers[0]
        self.assertIsInstance(h1, log.NullHandler)

    def test_when_logger(self):
        l = log.get_logger(logging.getLogger("foo"))
        h1 = l.handlers[0]
        self.assertIsInstance(h1, log.NullHandler)

    def test_with_custom_handler(self):
        l = logging.getLogger("bar")
        handler = log.NullHandler()
        l.addHandler(handler)

        l = log.get_logger("bar")
        self.assertIs(l.handlers[0], handler)

    def test_anon_logger(self):
        l = log.anon_logger("test_anon_logger")
        self.assertIsInstance(l.handlers[0], log.NullHandler)

    def test_get_loglevel(self):
        self.assertEqual(log.get_loglevel("DEBUG"), logging.DEBUG)
        self.assertEqual(log.get_loglevel("ERROR"), logging.ERROR)
        self.assertEqual(log.get_loglevel(logging.INFO), logging.INFO)


class test_safe_format(TestCase):

    def test_formatting(self):
        fmt = "The %r jumped over the %s"
        args = ["frog", "elephant"]

        res = list(log.safeify_format(fmt, *args))
        self.assertListEqual(res, ["'frog'", "elephant"])


class test_LogMixin(TestCase):

    def setUp(self):
        self.log = log.Log("Log", Mock())
        self.logger = self.log.logger

    def test_debug(self):
        self.log.debug("debug")
        self.logger.log.assert_called_with(logging.DEBUG, "Log - debug")

    def test_info(self):
        self.log.info("info")
        self.logger.log.assert_called_with(logging.INFO, "Log - info")

    def test_warning(self):
        self.log.warn("warning")
        self.logger.log.assert_called_with(logging.WARN, "Log - warning")

    def test_error(self):
        self.log.error("error", exc_info="exc")
        self.logger.log.assert_called_with(logging.ERROR, "Log - error",
                                      exc_info="exc")

    def test_critical(self):
        self.log.critical("crit", exc_info="exc")
        self.logger.log.assert_called_with(logging.CRITICAL, "Log - crit",
                                      exc_info="exc")

    def test_error_when_DISABLE_TRACEBACKS(self):
        log.DISABLE_TRACEBACKS = True
        try:
            self.log.error("error")
            self.logger.log.assert_called_with(logging.ERROR, "Log - error")
        finally:
            log.DISABLE_TRACEBACKS = False

    def test_get_loglevel(self):
        self.assertEqual(self.log.get_loglevel("DEBUG"), logging.DEBUG)
        self.assertEqual(self.log.get_loglevel("ERROR"), logging.ERROR)
        self.assertEqual(self.log.get_loglevel(logging.INFO), logging.INFO)

    def test_is_enabled_for(self):
        self.logger.isEnabledFor.return_value = True
        self.assertTrue(self.log.is_enabled_for("DEBUG"))
        self.logger.isEnabledFor.assert_called_with(logging.DEBUG)

    def test_LogMixin_get_logger(self):
        self.assertIs(log.LogMixin().get_logger(),
                      logging.getLogger("LogMixin"))

    def test_Log_get_logger(self):
        self.assertIs(log.Log("test_Log").get_logger(),
                      logging.getLogger("test_Log"))

    def test_log_when_not_enabled(self):
        self.logger.isEnabledFor.return_value = False
        self.log.debug("debug")
        self.assertFalse(self.logger.log.called)

    def test_log_with_format(self):
        self.log.debug("Host %r removed", "example.com")
        self.logger.log.assert_called_with(logging.DEBUG,
                "Log - Host %s removed", "'example.com'")


class test_setup_logging(TestCase):

    @patch("logging.getLogger")
    def test_set_up_default_values(self, getLogger):
        logger = logging.getLogger.return_value = Mock()
        logger.handlers = []
        log.setup_logging()

        logger.setLevel.assert_called_with(logging.ERROR)
        self.assertTrue(logger.addHandler.called)
        ah_args, _ = logger.addHandler.call_args
        handler = ah_args[0]
        self.assertIsInstance(handler, logging.StreamHandler)
        self.assertIs(handler.stream, sys.__stderr__)

    @patch("logging.getLogger")
    @patch("kombu.log.WatchedFileHandler")
    def test_setup_custom_values(self, getLogger, WatchedFileHandler):
        logger = logging.getLogger.return_value = Mock()
        logger.handlers = []
        log.setup_logging(loglevel=logging.DEBUG, logfile="/var/logfile")

        logger.setLevel.assert_called_with(logging.DEBUG)
        self.assertTrue(logger.addHandler.called)
        self.assertTrue(WatchedFileHandler.called)

    @patch("logging.getLogger")
    def test_logger_already_setup(self, getLogger):
        logger = logging.getLogger.return_value = Mock()
        logger.handlers = [Mock()]
        log.setup_logging()

        self.assertFalse(logger.setLevel.called)
