"""Tests for the 'zero' plugin"""

import unittest

from mediafile import MediaFile

from beets.library import Item
from beets.test.helper import TestHelper, control_stdin
from beets.util import syspath
from beetsplug.zero import ZeroPlugin


class ZeroPluginTest(unittest.TestCase, TestHelper):
    def setUp(self):
        self.setup_beets()
        self.config["zero"] = {
            "fields": [],
            "keep_fields": [],
            "update_database": False,
        }

    def tearDown(self):
        ZeroPlugin.listeners = None
        self.teardown_beets()
        self.unload_plugins()

    def test_no_patterns(self):
        self.config["zero"]["fields"] = ["comments", "month"]

        item = self.add_item_fixture(
            comments="test comment",
            title="Title",
            month=1,
            year=2000,
        )
        item.write()

        self.load_plugins("zero")
        item.write()

        mf = MediaFile(syspath(item.path))
        self.assertIsNone(mf.comments)
        self.assertIsNone(mf.month)
        self.assertEqual(mf.title, "Title")
        self.assertEqual(mf.year, 2000)

    def test_pattern_match(self):
        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["comments"] = ["encoded by"]

        item = self.add_item_fixture(comments="encoded by encoder")
        item.write()

        self.load_plugins("zero")
        item.write()

        mf = MediaFile(syspath(item.path))
        self.assertIsNone(mf.comments)

    def test_pattern_nomatch(self):
        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["comments"] = ["encoded by"]

        item = self.add_item_fixture(comments="recorded at place")
        item.write()

        self.load_plugins("zero")
        item.write()

        mf = MediaFile(syspath(item.path))
        self.assertEqual(mf.comments, "recorded at place")

    def test_do_not_change_database(self):
        self.config["zero"]["fields"] = ["year"]

        item = self.add_item_fixture(year=2000)
        item.write()

        self.load_plugins("zero")
        item.write()

        self.assertEqual(item["year"], 2000)

    def test_change_database(self):
        self.config["zero"]["fields"] = ["year"]
        self.config["zero"]["update_database"] = True

        item = self.add_item_fixture(year=2000)
        item.write()

        self.load_plugins("zero")
        item.write()

        self.assertEqual(item["year"], 0)

    def test_album_art(self):
        self.config["zero"]["fields"] = ["images"]

        path = self.create_mediafile_fixture(images=["jpg"])
        item = Item.from_path(path)

        self.load_plugins("zero")
        item.write()

        mf = MediaFile(syspath(path))
        self.assertFalse(mf.images)

    def test_auto_false(self):
        self.config["zero"]["fields"] = ["year"]
        self.config["zero"]["update_database"] = True
        self.config["zero"]["auto"] = False

        item = self.add_item_fixture(year=2000)
        item.write()

        self.load_plugins("zero")
        item.write()

        self.assertEqual(item["year"], 2000)

    def test_subcommand_update_database_true(self):
        item = self.add_item_fixture(
            year=2016, day=13, month=3, comments="test comment"
        )
        item.write()
        item_id = item.id
        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["update_database"] = True
        self.config["zero"]["auto"] = False

        self.load_plugins("zero")
        with control_stdin("y"):
            self.run_command("zero")

        mf = MediaFile(syspath(item.path))
        item = self.lib.get_item(item_id)

        self.assertEqual(item["year"], 2016)
        self.assertEqual(mf.year, 2016)
        self.assertIsNone(mf.comments)
        self.assertEqual(item["comments"], "")

    def test_subcommand_update_database_false(self):
        item = self.add_item_fixture(
            year=2016, day=13, month=3, comments="test comment"
        )
        item.write()
        item_id = item.id

        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["update_database"] = False
        self.config["zero"]["auto"] = False

        self.load_plugins("zero")
        with control_stdin("y"):
            self.run_command("zero")

        mf = MediaFile(syspath(item.path))
        item = self.lib.get_item(item_id)

        self.assertEqual(item["year"], 2016)
        self.assertEqual(mf.year, 2016)
        self.assertEqual(item["comments"], "test comment")
        self.assertIsNone(mf.comments)

    def test_subcommand_query_include(self):
        item = self.add_item_fixture(
            year=2016, day=13, month=3, comments="test comment"
        )

        item.write()

        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["update_database"] = False
        self.config["zero"]["auto"] = False

        self.load_plugins("zero")
        self.run_command("zero", "year: 2016")

        mf = MediaFile(syspath(item.path))

        self.assertEqual(mf.year, 2016)
        self.assertIsNone(mf.comments)

    def test_subcommand_query_exclude(self):
        item = self.add_item_fixture(
            year=2016, day=13, month=3, comments="test comment"
        )

        item.write()

        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["update_database"] = False
        self.config["zero"]["auto"] = False

        self.load_plugins("zero")
        self.run_command("zero", "year: 0000")

        mf = MediaFile(syspath(item.path))

        self.assertEqual(mf.year, 2016)
        self.assertEqual(mf.comments, "test comment")

    def test_no_fields(self):
        item = self.add_item_fixture(year=2016)
        item.write()
        mediafile = MediaFile(syspath(item.path))
        self.assertEqual(mediafile.year, 2016)

        item_id = item.id

        self.load_plugins("zero")
        with control_stdin("y"):
            self.run_command("zero")

        item = self.lib.get_item(item_id)

        self.assertEqual(item["year"], 2016)
        self.assertEqual(mediafile.year, 2016)

    def test_whitelist_and_blacklist(self):
        item = self.add_item_fixture(year=2016)
        item.write()
        mf = MediaFile(syspath(item.path))
        self.assertEqual(mf.year, 2016)

        item_id = item.id
        self.config["zero"]["fields"] = ["year"]
        self.config["zero"]["keep_fields"] = ["comments"]

        self.load_plugins("zero")
        with control_stdin("y"):
            self.run_command("zero")

        item = self.lib.get_item(item_id)

        self.assertEqual(item["year"], 2016)
        self.assertEqual(mf.year, 2016)

    def test_keep_fields(self):
        item = self.add_item_fixture(year=2016, comments="test comment")
        self.config["zero"]["keep_fields"] = ["year"]
        self.config["zero"]["fields"] = None
        self.config["zero"]["update_database"] = True

        tags = {
            "comments": "test comment",
            "year": 2016,
        }
        self.load_plugins("zero")

        z = ZeroPlugin()
        z.write_event(item, item.path, tags)
        self.assertIsNone(tags["comments"])
        self.assertEqual(tags["year"], 2016)

    def test_keep_fields_removes_preserved_tags(self):
        self.config["zero"]["keep_fields"] = ["year"]
        self.config["zero"]["fields"] = None
        self.config["zero"]["update_database"] = True

        z = ZeroPlugin()

        self.assertNotIn("id", z.fields_to_progs)

    def test_fields_removes_preserved_tags(self):
        self.config["zero"]["fields"] = ["year id"]
        self.config["zero"]["update_database"] = True

        z = ZeroPlugin()

        self.assertNotIn("id", z.fields_to_progs)

    def test_empty_query_n_response_no_changes(self):
        item = self.add_item_fixture(
            year=2016, day=13, month=3, comments="test comment"
        )
        item.write()
        item_id = item.id
        self.config["zero"]["fields"] = ["comments"]
        self.config["zero"]["update_database"] = True
        self.config["zero"]["auto"] = False

        self.load_plugins("zero")
        with control_stdin("n"):
            self.run_command("zero")

        mf = MediaFile(syspath(item.path))
        item = self.lib.get_item(item_id)

        self.assertEqual(item["year"], 2016)
        self.assertEqual(mf.year, 2016)
        self.assertEqual(mf.comments, "test comment")
        self.assertEqual(item["comments"], "test comment")


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


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