# This file is part of beets.
# Copyright 2016, Fabrice Laporte.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

"""Tests for the 'ftintitle' plugin."""


import unittest

from beets.test.helper import TestHelper
from beetsplug import ftintitle


class FtInTitlePluginFunctional(unittest.TestCase, TestHelper):
    def setUp(self):
        """Set up configuration"""
        self.setup_beets()
        self.load_plugins("ftintitle")

    def tearDown(self):
        self.unload_plugins()
        self.teardown_beets()

    def _ft_add_item(self, path, artist, title, aartist):
        return self.add_item(
            path=path,
            artist=artist,
            artist_sort=artist,
            title=title,
            albumartist=aartist,
        )

    def _ft_set_config(self, ftformat, drop=False, auto=True):
        self.config["ftintitle"]["format"] = ftformat
        self.config["ftintitle"]["drop"] = drop
        self.config["ftintitle"]["auto"] = auto

    def test_functional_drop(self):
        item = self._ft_add_item("/", "Alice ft Bob", "Song 1", "Alice")
        self.run_command("ftintitle", "-d")
        item.load()
        self.assertEqual(item["artist"], "Alice")
        self.assertEqual(item["title"], "Song 1")

    def test_functional_not_found(self):
        item = self._ft_add_item("/", "Alice ft Bob", "Song 1", "George")
        self.run_command("ftintitle", "-d")
        item.load()
        # item should be unchanged
        self.assertEqual(item["artist"], "Alice ft Bob")
        self.assertEqual(item["title"], "Song 1")

    def test_functional_custom_format(self):
        self._ft_set_config("feat. {0}")
        item = self._ft_add_item("/", "Alice ft Bob", "Song 1", "Alice")
        self.run_command("ftintitle")
        item.load()
        self.assertEqual(item["artist"], "Alice")
        self.assertEqual(item["title"], "Song 1 feat. Bob")

        self._ft_set_config("featuring {0}")
        item = self._ft_add_item("/", "Alice feat. Bob", "Song 1", "Alice")
        self.run_command("ftintitle")
        item.load()
        self.assertEqual(item["artist"], "Alice")
        self.assertEqual(item["title"], "Song 1 featuring Bob")

        self._ft_set_config("with {0}")
        item = self._ft_add_item("/", "Alice feat Bob", "Song 1", "Alice")
        self.run_command("ftintitle")
        item.load()
        self.assertEqual(item["artist"], "Alice")
        self.assertEqual(item["title"], "Song 1 with Bob")


class FtInTitlePluginTest(unittest.TestCase):
    def setUp(self):
        """Set up configuration"""
        ftintitle.FtInTitlePlugin()

    def test_find_feat_part(self):
        test_cases = [
            {
                "artist": "Alice ft. Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice feat Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice featuring Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice & Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice and Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice With Bob",
                "album_artist": "Alice",
                "feat_part": "Bob",
            },
            {
                "artist": "Alice defeat Bob",
                "album_artist": "Alice",
                "feat_part": None,
            },
            {
                "artist": "Alice & Bob",
                "album_artist": "Bob",
                "feat_part": "Alice",
            },
            {
                "artist": "Alice ft. Bob",
                "album_artist": "Bob",
                "feat_part": "Alice",
            },
            {
                "artist": "Alice ft. Carol",
                "album_artist": "Bob",
                "feat_part": None,
            },
        ]

        for test_case in test_cases:
            feat_part = ftintitle.find_feat_part(
                test_case["artist"], test_case["album_artist"]
            )
            self.assertEqual(feat_part, test_case["feat_part"])

    def test_split_on_feat(self):
        parts = ftintitle.split_on_feat("Alice ft. Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice feat Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice feat. Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice featuring Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice & Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice and Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice With Bob")
        self.assertEqual(parts, ("Alice", "Bob"))
        parts = ftintitle.split_on_feat("Alice defeat Bob")
        self.assertEqual(parts, ("Alice defeat Bob", None))

    def test_contains_feat(self):
        self.assertTrue(ftintitle.contains_feat("Alice ft. Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice feat. Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice feat Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice featuring Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice & Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice and Bob"))
        self.assertTrue(ftintitle.contains_feat("Alice With Bob"))
        self.assertFalse(ftintitle.contains_feat("Alice defeat Bob"))
        self.assertFalse(ftintitle.contains_feat("Aliceft.Bob"))


def suite():
    return unittest.TestLoader().loadTestsFromName(__name__)


if __name__ == "__main__":
    unittest.main(defaultTest="suite")
