# TODO: Implement skipped tests

import unittest

import pytest

from sickchill import settings
from sickchill.oldbeard import common


class QualityStringTests(unittest.TestCase):
    """
    Test Case for strings in common.Quality
    """

    settings.QUALITY_ALLOW_HEVC = True
    test_cases = {
        "sd_tv": [
            "Test.Show.S01E02.PDTV.XViD-GROUP",
            "Test.Show.S01E02.PDTV.x264-GROUP",
            "Test.Show.S01E02.HDTV.XViD-GROUP",
            "Test.Show.S01E02.HDTV.x264-GROUP",
            "Test.Show.S01E02.DSR.XViD-GROUP",
            "Test.Show.S01E02.DSR.x264-GROUP",
            "Test.Show.S01E02.TVRip.XViD-GROUP",
            "Test.Show.S01E02.TVRip.x264-GROUP",
            "Test.Show.S01E02.WEBRip.XViD-GROUP",
            "Test.Show.S01E02.WEBRip.x264-GROUP",
            "Test.Show.S01E02.WEB-DL.x264-GROUP",
            "Test.Show.S01E02.WEB-DL.AAC2.0.H.264-GROUP",
            "Test.Show.S01E02 WEB-DL H 264-GROUP",
            "Test.Show.S01E02_WEB-DL_H_264-GROUP",
            "Test.Show.S01E02.WEB-DL.AAC2.0.H264-GROUP",
        ],
        "sd_dvd": [
            "Test.Show.S01E02.480P.DVDrip.HEVC.X265",
            "Test.Show.S01E02.DVDRiP.XViD-GROUP",
            "Test.Show.S01E02.DVDRiP.DiVX-GROUP",
            "Test.Show.S01E02.DVDRiP.x264-GROUP",
            "Test.Show.S01E02.DVDRip.WS.XViD-GROUP",
            "Test.Show.S01E02.DVDRip.WS.DiVX-GROUP",
            "Test.Show.S01E02.DVDRip.WS.x264-GROUP",
            "Test.Show.S01E02.BDRIP.XViD-GROUP",
            "Test.Show.S01E02.BDRIP.DiVX-GROUP",
            "Test.Show.S01E02.BDRIP.x264-GROUP",
            "Test.Show.S01E02.BDRIP.WS.XViD-GROUP",
            "Test.Show.S01E02.BDRIP.WS.DiVX-GROUP",
            "Test.Show.S01E02.BDRIP.WS.x264-GROUP",
        ],
        "hd_tv": ["Test.Show.S01E02.720p.HDTV.x264-GROUP", "Test.Show.S01E02.HR.WS.PDTV.x264-GROUP"],
        "raw_hd_tv": [
            "Test.Show.S01E02.720p.HDTV.DD5.1.MPEG2-GROUP",
            "Test.Show.S01E02.1080i.HDTV.DD2.0.MPEG2-GROUP",
            "Test.Show.S01E02.1080i.HDTV.H.264.DD2.0-GROUP",
            "Test Show - S01E02 - 1080i HDTV MPA1.0 H.264 - GROUP",
            "Test.Show.S01E02.1080i.HDTV.DD.5.1.h264-GROUP",
        ],
        "full_hd_tv": ["Test.Show.S01E02.1080p.HDTV.x264-GROUP"],
        "hd_web_dl": [
            "Test.Show.S01E02.720p.WEB-DL-GROUP",
            "Test.Show.S01E02.720p.WEBRip-GROUP",
            "Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP",
            "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP",
            "Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP",
            "Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP",
            "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP",
            "Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP",
            "Test.Show.S01E02.Episode.Name.Itunes.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.ItunesHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.ItunesUHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.Itunes.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.ItunesHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.ItunesUHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.AMZN.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.Amazon.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.AmazonHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.AmazonUHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.AMZN.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.Amazon.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.AmazonHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.720p.AmazonUHD.WEB-DL.x264",
            # German dubs
            "Test.Show.S01E02.Episode.Name.German.DD51.Synced.DL.iTunesHD.AVC",
            "Test.Show.S01E02.Episode.Name.German.DD51.Synced.DL.AmazonHD.x264",
            "Test.Show.S01E02.Episode.Name.German.Dubbed.DL.iTunesHD.x264",
            "Test.Show.S01E02.Episode.Name.German.DD51.DL.NetflixHD.x264",
            "Test.Show.S01E02.Episode.Name.German.DD51.DL.NetflixUHD.x264",
        ],
        "full_hd_web_dl": [
            "Test.Show.S01E02.1080p.WEB-DL-GROUP",
            "Test.Show.S01E02.1080p.WEBRip-GROUP",
            "Test.Show.S01E02.WEBRip.1080p.H.264.AAC.2.0-GROUP",
            "Test.Show.S01E02.WEBRip.1080p.H264.AAC.2.0-GROUP",
            "Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP",
            "Test Show S01E02 1080p iTunes H 264 AAC-GROUP",
            "Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP",
            "Test.Show.S01E02.Episode.Name.1080p.Itunes.WEB-DL.x264" "Test.Show.S01E02.Episode.Name.1080p.ItunesHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.1080p.ItunesUHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.1080p.AMZN.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.1080p.Amazon.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.1080p.AmazonUHD.WEB-DL.x264",
            "Test.Show.S01E02.Episode.Name.1080p.AmazonHD.WEB-DL.x264",
            # German dubs
            "Test.Show.S01E02.Episode.Name.German.DD51.Synced.DL.1080p.iTunesHD.AVC",
            "Test.Show.S01E02.Episode.Name.German.DD51.Synced.DL.1080p.AmazonHD.x264",
            "Test.Show.S01E02.Episode.Name.German.Dubbed.DL.1080p.iTunesHD.x264",
            "Test.Show.S01E02.Episode.Name.German.DD51.DL.1080p.NetflixHD.x264",
            "Test.Show.S01E02.Episode.Name.German.DD51.DL.1080p.NetflixUHD.x264",
        ],
        "hd_bluray": ["Test.Show.S01E02.720p.BluRay.x264-GROUP", "Test.Show.S01E02.720p.HDDVD.x264-GROUP"],
        "full_hd_bluray": ["Test.Show.S01E02.1080p.BluRay.x264-GROUP", "Test.Show.S01E02.1080p.HDDVD.x264-GROUP"],
        "unknown": [
            "Test.Show.S01E02-SiCKCHILL",
            "Test.Show.S01E01-20.1080i.[Mux.-.1080i.-.H264.-.Ac3.].HDTVMux.GROUP",
        ],
    }

    def test_sd_tv(self):
        """
        Test SDTV against nameQuality
        """
        cur_test = "sd_tv"
        cur_qual = common.Quality.SDTV

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_sd_dvd(self):
        """
        Test SDDVD against nameQuality
        """
        cur_test = "sd_dvd"
        cur_qual = common.Quality.SDDVD

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_hd_tv(self):
        """
        Test HDTV against nameQuality
        """
        cur_test = "hd_tv"
        cur_qual = common.Quality.HDTV

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test), test
                else:
                    assert cur_qual != common.Quality.nameQuality(test), test

    def test_raw_hd_tv(self):
        """
        Test RAWHDTV against nameQuality
        """
        cur_test = "raw_hd_tv"
        cur_qual = common.Quality.RAWHDTV

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test), test
                else:
                    assert cur_qual != common.Quality.nameQuality(test), test

    def test_full_hd_tv(self):
        """
        Test FULLHDTV against nameQuality
        """
        cur_test = "full_hd_tv"
        cur_qual = common.Quality.FULLHDTV

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_hd_web_dl(self):
        """
        Test HDWEBDL against nameQuality
        """
        cur_test = "hd_web_dl"
        cur_qual = common.Quality.HDWEBDL

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_full_hd_web_dl(self):
        """
        Test FULLHDWEBDL against nameQuality
        """
        cur_test = "full_hd_web_dl"
        cur_qual = common.Quality.FULLHDWEBDL

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_hd_bluray(self):
        """
        Test HDBLURAY against nameQuality
        """
        cur_test = "hd_bluray"
        cur_qual = common.Quality.HDBLURAY

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_full_hd_bluray(self):
        """
        Test FULLHDBLURAY against nameQuality
        """
        cur_test = "full_hd_bluray"
        cur_qual = common.Quality.FULLHDBLURAY

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_unknown(self):
        """
        Test UNKNOWN against nameQuality
        """
        cur_test = "unknown"
        cur_qual = common.Quality.UNKNOWN

        for name, tests in self.test_cases.items():
            for test in tests:
                if name == cur_test:
                    assert cur_qual == common.Quality.nameQuality(test)
                else:
                    assert cur_qual != common.Quality.nameQuality(test)

    def test_anime(self):
        """
        Test Anime against nameQuality
        """
        test_cases = {
            "sd_dvd": [
                "[DeadFish].Shingeki.no.Kyojin.-.01.-.OVA.[DVD][480p][AAC].mp4",
            ],
            "full_hd_bluray": [
                "[Hatsuyuki-Kaitou]_Shingeki_no_Kyojin_-_Special_02_[BD_1080p][10bit][FLAC][4D908801].mkv",
            ],
        }
        test_quality = {
            "sd_tv": common.Quality.SDTV,
            "sd_dvd": common.Quality.SDDVD,
            "raw_hd_tv": common.Quality.RAWHDTV,
            "hd_tv": common.Quality.HDTV,
            "hd_web_dl": common.Quality.HDWEBDL,
            "hd_bluray": common.Quality.HDBLURAY,
            "full_hd_tv": common.Quality.FULLHDTV,
            "full_hd_web_dl": common.Quality.FULLHDWEBDL,
            "full_hd_bluray": common.Quality.FULLHDBLURAY,
            "unknown": common.Quality.UNKNOWN,
        }
        for cur_test, expected_qual in test_quality.items():
            for qual, tests in test_cases.items():
                for name in tests:
                    name_quality = common.Quality.nameQuality(name, anime=True)
                    name_info = (qual, name, expected_qual, common.Quality.nameQuality(name, anime=True))
                    if qual == cur_test:
                        assert expected_qual == name_quality, name_info
                    else:
                        assert expected_qual != name_quality, name_info


class QualityTests(unittest.TestCase):
    """
    Test Case for common.Quality
    """

    # TODO: repack / proper ? air-by-date ? season rip? multi-ep?
    # reverse parsing does not work
    def test_reverse_parsing(self):
        """
        Test reverse parsing for all qualities
        """
        tests = [
            (common.Quality.SDTV, "Test Show - S01E02 - SDTV - GROUP"),
            (common.Quality.SDDVD, "Test Show - S01E02 - SD DVD - GROUP"),
            (common.Quality.HDTV, "Test Show - S01E02 - HDTV - GROUP"),
            (common.Quality.RAWHDTV, "Test Show - S01E02 - RawHD - GROUP"),
            (common.Quality.FULLHDTV, "Test Show - S01E02 - 1080p HDTV - GROUP"),
            (common.Quality.HDWEBDL, "Test Show - S01E02 - 720p WEB-DL - GROUP"),
            (common.Quality.FULLHDWEBDL, "Test Show - S01E02 - 1080p WEB-DL - GROUP"),
            (common.Quality.HDBLURAY, "Test Show - S01E02 - 720p BluRay - GROUP"),
            (common.Quality.FULLHDBLURAY, "Test Show - S01E02 - 1080p BluRay - GROUP"),
            (common.Quality.UNKNOWN, "Test Show - S01E02 - Unknown - SiCKCHILL"),
        ]
        for test in tests:
            quality, test = test
            assert quality == common.Quality.nameQuality(test), (quality, common.Quality.nameQuality(test), test)

    @unittest.skip("Not yet implemented")
    def test_get_status_strings(self):
        """
        Test _getStatusStrings
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_combine_qualities(self):
        """
        Test combineQualities
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_split_quality(self):
        """
        Test splitQuality
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_name_quality(self):
        """
        Test nameQuality
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_scene_quality(self):
        """
        Test scene_quality
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_quality_from_file_meta(self):
        """
        Test qualityFromFileMeta
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_composite_status(self):
        """
        Test compositeStatus
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_quality_downloaded(self):
        """
        Test qualityDownloaded
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_split_composite_status(self):
        """
        Test splitCompositeStatus
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_scene_quality_from_name(self):
        """
        Test sceneQualityFromName
        """
        pass

    @unittest.skip("Not yet implemented")
    def test_status_from_name(self):
        """
        Test statusFromName
        """
        pass


class StatusStringsTests(unittest.TestCase):
    """
    Test Case for common.StatusStrings
    """

    # TODO: Split tests into separate tests and add additional tests

    def test_all(self):
        """
        Run all status strings tests
        """
        status_strings = common.statusStrings

        valid = 1, 112, "1", "112"
        unused = 122, 99998989899878676, "99998989899878676", None
        invalid = "Elephant", (4, 1), [1, 233, 4, None]

        for i in valid:
            assert i in status_strings

        for i in unused:
            assert i not in status_strings
            with pytest.raises(KeyError):
                status_strings[i]

        for i in status_strings:
            assert status_strings[i] == status_strings[str(i)]
            assert (i in status_strings) == (str(i) in status_strings)

        for i in status_strings.qualities:
            assert status_strings[i] == status_strings[str(i)]
            assert (i in status_strings) == (str(i) in status_strings)

        for i in invalid:
            with self.assertRaises(TypeError):
                status_strings[i] = 1

        for i in unused:
            if i is None:
                with self.assertRaises(TypeError):
                    status_strings[str(i)] = 1  # 'None' is not None
                status_strings[i] = 1  # ...but None can still be used as a key
            else:
                status_strings[str(i)] = 1
            assert status_strings[i] == 1


class OverviewTests(unittest.TestCase):
    """
    Test common.Overview
    """

    def test_overview_strings(self):
        """
        Test common.Overview.overviewStrings
        """
        overview = common.Overview()

        assert overview.overviewStrings[overview.SKIPPED] == "skipped"
        assert overview.overviewStrings[overview.WANTED] == "wanted"
        assert overview.overviewStrings[overview.QUAL] == "qual"
        assert overview.overviewStrings[overview.GOOD] == "good"
        assert overview.overviewStrings[overview.UNAIRED] == "unaired"
        assert overview.overviewStrings[overview.SNATCHED] == "snatched"


if __name__ == "__main__":
    print("=======================")
    print("STARTING - COMMON TESTS")
    print("=======================")

    SUITE = unittest.TestLoader().loadTestsFromTestCase(QualityStringTests)
    unittest.TextTestRunner(verbosity=2).run(SUITE)

    SUITE = unittest.TestLoader().loadTestsFromTestCase(QualityTests)
    unittest.TextTestRunner(verbosity=2).run(SUITE)

    SUITE = unittest.TestLoader().loadTestsFromTestCase(StatusStringsTests)
    unittest.TextTestRunner(verbosity=2).run(SUITE)

    SUITE = unittest.TestLoader().loadTestsFromTestCase(OverviewTests)
    unittest.TextTestRunner(verbosity=2).run(SUITE)
