# Copyright (C) 2005-2011 Canonical Ltd
# Copyright (C) 2018-2020 Breezy Developers
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

import os

from ... import tests
from ...conflicts import resolve
from ...tests import scenarios
from ...tests.test_conflicts import vary_by_conflicts
from .. import conflicts as bzr_conflicts

load_tests = scenarios.load_tests_apply_scenarios


class TestPerConflict(tests.TestCase):
    scenarios = scenarios.multiply_scenarios(vary_by_conflicts())

    def test_stringification(self):
        text = str(self.conflict)
        self.assertContainsString(text, self.conflict.path)
        self.assertContainsString(text.lower(), "conflict")
        self.assertContainsString(repr(self.conflict), self.conflict.__class__.__name__)

    def test_stanza_roundtrip(self):
        p = self.conflict
        o = bzr_conflicts.Conflict.factory(**p.as_stanza().as_dict())
        self.assertEqual(o, p)

        self.assertIsInstance(o.path, str)

        if o.file_id is not None:
            self.assertIsInstance(o.file_id, bytes)

        conflict_path = getattr(o, "conflict_path", None)
        if conflict_path is not None:
            self.assertIsInstance(conflict_path, str)

        conflict_file_id = getattr(o, "conflict_file_id", None)
        if conflict_file_id is not None:
            self.assertIsInstance(conflict_file_id, bytes)

    def test_stanzification(self):
        stanza = self.conflict.as_stanza()
        if "file_id" in stanza:
            # In Stanza form, the file_id has to be unicode.
            self.assertStartsWith(stanza["file_id"], "\xeed")
        self.assertStartsWith(stanza["path"], "p\xe5th")
        if "conflict_path" in stanza:
            self.assertStartsWith(stanza["conflict_path"], "p\xe5th")
        if "conflict_file_id" in stanza:
            self.assertStartsWith(stanza["conflict_file_id"], "\xeed")


class TestConflicts(tests.TestCaseWithTransport):
    def test_resolve_conflict_dir(self):
        tree = self.make_branch_and_tree(".")
        self.build_tree_contents(
            [
                ("hello", b"hello world4"),
                ("hello.THIS", b"hello world2"),
                ("hello.BASE", b"hello world1"),
            ]
        )
        os.mkdir("hello.OTHER")
        tree.add("hello", ids=b"q")
        l = bzr_conflicts.ConflictList([bzr_conflicts.TextConflict("hello")])
        l.remove_files(tree)

    def test_select_conflicts(self):
        tree = self.make_branch_and_tree(".")
        clist = bzr_conflicts.ConflictList

        def check_select(not_selected, selected, paths, **kwargs):
            self.assertEqual(
                (not_selected, selected),
                tree_conflicts.select_conflicts(tree, paths, **kwargs),
            )

        foo = bzr_conflicts.ContentsConflict("foo")
        bar = bzr_conflicts.ContentsConflict("bar")
        tree_conflicts = clist([foo, bar])

        check_select(clist([bar]), clist([foo]), ["foo"])
        check_select(clist(), tree_conflicts, [""], ignore_misses=True, recurse=True)

        foobaz = bzr_conflicts.ContentsConflict("foo/baz")
        tree_conflicts = clist([foobaz, bar])

        check_select(
            clist([bar]), clist([foobaz]), ["foo"], ignore_misses=True, recurse=True
        )

        qux = bzr_conflicts.PathConflict("qux", "foo/baz")
        tree_conflicts = clist([qux])

        check_select(clist(), tree_conflicts, ["foo"], ignore_misses=True, recurse=True)
        check_select(tree_conflicts, clist(), ["foo"], ignore_misses=True)

    def test_resolve_conflicts_recursive(self):
        tree = self.make_branch_and_tree(".")
        self.build_tree(["dir/", "dir/hello"])
        tree.add(["dir", "dir/hello"])

        dirhello = [bzr_conflicts.TextConflict("dir/hello")]
        tree.set_conflicts(dirhello)

        resolve(tree, ["dir"], recursive=False, ignore_misses=True)
        self.assertEqual(dirhello, tree.conflicts())

        resolve(tree, ["dir"], recursive=True, ignore_misses=True)
        self.assertEqual(bzr_conflicts.ConflictList([]), tree.conflicts())
