# -*- coding: utf-8 -*-
# Copyright: 2016, Ableton AG, Berlin. All rights reserved.
import unittest

from abl.util import LockFileObtainException
from abl.vpath.base import URI
from abl.webconnector.fileprocessing import (
    group_files_by_pivot_most_recent_first,
    mark_as_processed,
    pivot_lockfile,
)

from .common import cleanup_memory_fs, create_file


def files_sorted_by_path(files):
    return sorted(files, key=lambda f: f.path)


class FileGroupingTests(unittest.TestCase):
    def tearDown(self):
        super(FileGroupingTests, self).tearDown()
        cleanup_memory_fs()

    def test_pivots_each_form_a_group(self):
        base = URI("memory:///")
        files = [create_file(base / "event_{}.log".format(i)) for i in xrange(10)]
        result = [g.next() for g in group_files_by_pivot_most_recent_first(base)]
        self.assertEqual(files_sorted_by_path(files), files_sorted_by_path(result))

    def test_groups_contain_pivots_and_same_prefix_files(self):
        base = URI("memory:///")
        group_a = set(
            (
                create_file(base / "event_1.log"),
                create_file(base / "event_1.wc"),
                create_file(base / "event_1.crash"),
            )
        )

        newest_file = create_file(base / "event_2.log")
        group_b = set((newest_file,))

        for group_a_file in group_a:
            group_a_file._manipulate(mtime=newest_file.mtime() - 1)

        a, b = [set(g) for g in group_files_by_pivot_most_recent_first(base)]
        # this is buttugly, but apparently abl.vpath doesn't work as hashable/comparable
        # which needs fixing - but not now.
        self.assertEqual(files_sorted_by_path(group_b), files_sorted_by_path(a))
        self.assertEqual(files_sorted_by_path(group_a), files_sorted_by_path(b))

    def test_groups_with_locks_arent_returned(self):
        base = URI("memory:///")
        lockfile = create_file(pivot_lockfile(create_file(base / "event_1.log")))
        lockfile._manipulate(lock=True)
        groups = list(group_files_by_pivot_most_recent_first(base))
        self.assertEqual([], groups)

    def test_groups_are_returned_based_on_pivot_mtime(self):
        base = URI("memory:///")
        pivot_a = create_file(base / "event_1.log")
        pivot_b = create_file(base / "event_2.log")
        older = pivot_a.info().mtime
        newer = 2 * older
        pivot_a._manipulate(mtime=older)
        pivot_b._manipulate(mtime=newer)
        a, b = [g.next() for g in group_files_by_pivot_most_recent_first(base)]
        self.assertEqual(pivot_b, a)
        self.assertEqual(pivot_a, b)

        pivot_a._manipulate(mtime=newer)
        pivot_b._manipulate(mtime=older)
        a, b = [g.next() for g in group_files_by_pivot_most_recent_first(base)]
        self.assertEqual(pivot_a, a)
        self.assertEqual(pivot_b, b)

    def test_groups_maintain_lockfile_as_long_as_group_handle_exists(self):
        base = URI("memory:///")
        pivot = create_file(base / "event_1.log")
        got_group = False

        for g in group_files_by_pivot_most_recent_first(base):
            got_group = True
            try:
                with pivot_lockfile(pivot).lock(fail_on_lock=True):
                    pass
            except LockFileObtainException:
                pass
            else:
                self.assertTrue(False)

        self.assertTrue(got_group)

    def test_locks_for_processed_pivots_remain_the_same(self):
        base = URI("memory:///")
        pivot = create_file(base / "event_1.log")
        processed_pivot = mark_as_processed(pivot)
        self.assertFalse(pivot.exists())
        self.assertTrue(processed_pivot.exists())
        self.assertEqual(pivot_lockfile(pivot), pivot_lockfile(processed_pivot))

    def test_locks_follow_lives_naming_convention(self):
        """
        The protocol of appending .lock to the log-file
        stems from Live's Usage Data Writer. This test
        ensures we follow it.
        """
        base = URI("memory:///")
        pivot = base / "event_1.log"
        self.assertEqual(URI("memory:///event_1.log.lock"), pivot_lockfile(pivot))
