from __future__ import with_statement

import logging
import os
import sys
import tempfile

from unittest import TestCase

from abl.util import Bunch
from abl.vpath.base import URI
from abl.webconnector.reporting import WEBCONNECTOR_EXT


class AbletonWebConnector(object):
    pass


def win_esc(s):
    return s.replace("\\", "\\\\")


# inject our fake module into sys.modules
# so that ableton_ping.py will import it
# instead of the real thing
sys.modules["AbletonWebConnector"] = AbletonWebConnector

import AbletonWebConnector


class AbletonPingTests(TestCase):
    def ableton_ping_file(self):
        base = URI(os.path.join(os.getcwd(), __file__))
        return base.directory(4) / "Resources" / "scripts" / "ableton_ping.py"

    def test_logging_parameters(self):
        ping_file = self.ableton_ping_file()
        assert ping_file.exists(), ping_file

        g = {}
        execfile(str(ping_file), g)

        params = Bunch()

        def real_main(config, api_connector, usage_reporter=None):
            usage_reporter.log("start", foo="bar")
            params.config = Bunch(**config)
            usage_reporter.log("end")

        g["real_main"] = real_main

        param_file = tempfile.mktemp(suffix=".json")

        tempdir = tempfile.mkdtemp()
        log_file_path = win_esc(os.path.join(tempdir, "foo.log"))

        usage_report_prefix = "foobarbaz"

        with open(param_file, "w") as outf:
            outf.write(
                """
{

    "logging" : {
        "log_level" : "debug",
        "file_path" : "%s"
    },
    "usage_report_prefix" : "%s",
    "aip_usage_data_dir" : "%s"
}"""
                % (log_file_path, win_esc(usage_report_prefix), win_esc(tempdir))
            )

        g["main"](param_file)

        config = params.config
        self.assertEqual(config.logging["log_level"], "DEBUG")
        self.assertEqual(win_esc(config.logging["file_path"]), log_file_path)

        usage_file_name = win_esc(
            os.path.join(tempdir, "%s%s" % (usage_report_prefix, WEBCONNECTOR_EXT))
        )

        assert os.path.exists(usage_file_name)
        with open(usage_file_name) as inf:
            content = inf.read()
            assert "start" in content
            assert "end" in content
            assert '"foo": "bar"' in content

        # without setting the loglevel, we default to DEBUG
        with open(param_file, "w") as outf:
            outf.write(
                """
{

    "logging" : {
        "file_path" : "%s"
    }
}"""
                % log_file_path
            )
        g["main"](param_file)

        config = params.config
        self.assertEqual(config.logging["log_level"], "DEBUG")

        # we require a log_file!

        with open(param_file, "w") as outf:
            outf.write(
                """
{

    "logging" : {
        "log_level" : "ERROR"
    }
}"""
            )
        self.failUnlessRaises(SystemExit, g["main"], param_file)

        # now actually write something
        # and test the file truncation

        log_file_name = tempfile.mktemp()

        max_bytes = 1000

        with open(log_file_name, "w") as outf:
            outf.write("old\n" * 1000)
            outf.write(("middle\n" * 1000)[-max_bytes:])

        def logging_main(*args, **kwargs):
            for _ in xrange(100):
                logging.info("test")

        g["real_main"] = logging_main

        with open(param_file, "w") as outf:
            outf.write(
                """
{

    "logging" : {
        "file_path" : "%s"
    },
    "usage_report_prefix" : "foobarbaz",
    "aip_usage_data_dir" : "%s"
}"""
                % (win_esc(log_file_name), win_esc(tempdir))
            )

        g["main"](param_file, max_bytes=max_bytes)

        config = params.config
        self.assertEqual(config.logging["log_level"], "DEBUG")

        with open(log_file_name) as inf:
            content = inf.read()
            assert "test" in content
            assert "middle" in content
            assert "old" not in content
