/*
 * Copyright (C) 2011-2024 Michael Lugmair
 *
 * This file is part of sayonara player
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

#include "Common/SayonaraTest.h"
#include "Components/Lyrics/LyricsServerProvider.h"
#include "Components/Lyrics/LyricServer.h"
#include "Utils/LyricServerEntry.h"
#include "Utils/StandardPaths.h"

#include "Utils/Settings/Settings.h"

// access working directory with Test::Base::tempPath("somefile.txt");

namespace
{
	QString lyricConfigurationFile()
	{
		return ":/test/lyrics.json";
	}
}

class LyricsServerProviderTest :
	public Test::Base
{
	Q_OBJECT

	public:
		LyricsServerProviderTest() :
			Test::Base("LyricsServerProviderTest") {}

	private slots:

		// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
		[[maybe_unused]] void testLyricsPath()
		{
			auto path = Util::lyricsPath();
			QCOMPARE(path, tempPath(".qttest/cache/sayonara/lyrics"));
		}

		// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
		[[maybe_unused]] void testProviderDeliversStandardServers()
		{
			const auto servers = ::Lyrics::parseServers(lyricConfigurationFile());
			QCOMPARE(servers.count(), 3);
			QCOMPARE(servers[0]->name(), "Musixmatch");
			QCOMPARE(servers[1]->name(), "Genius");
			QCOMPARE(servers[2]->name(), "Sonichits");
		}

		// NOLINTNEXTLINE(readability-convert-member-functions-to-static, *-function-cognitive-complexity)
		[[maybe_unused]] void testSettingsAppliesToServerList()
		{
			using Lyrics::ServerEntry;

			struct ExpectedEntry
			{
				QString name;
				bool mapContainsName;
				bool isActivated;
			};

			struct TestCase
			{
				QList<Lyrics::ServerEntry> entries;
				QList<ExpectedEntry> expectedEntries;
			};
			const auto testCases = std::array {
				TestCase {
					{},
					{
						{"Musixmatch", false, true},
						{"Genius", false, true},
						{"Sonichits", false, true},
					}
				},
				TestCase {
					{
						ServerEntry("Sonichits", true)
					},
					{
						{"Sonichits", true, true},
						{"Musixmatch", false, true},
						{"Genius", false, true},
					}
				},
				TestCase {
					{
						ServerEntry("Inexistent", false)
					},
					{
						{"Musixmatch", false, true},
						{"Genius", false, true},
						{"Sonichits", false, true},
					}
				},
				TestCase {
					{
						ServerEntry("Sonichits", false),
						ServerEntry("Genius", true),
						ServerEntry("Musixmatch", false)
					},
					{
						{"Sonichits", true, false},
						{"Genius", true, true},
						{"Musixmatch", true, false},
					}
				}
			};

			for(const auto& testCase: testCases)
			{
				SetSetting(Set::Lyrics_ServerEntries, testCase.entries);
				const auto servers = Lyrics::getSortedServerList(false, lyricConfigurationFile());
				const auto map = Lyrics::getActiveEntryMap();

				QVERIFY(servers.count() == testCase.expectedEntries.count());

				for(int i = 0; i < servers.count(); i++)
				{
					const auto name = servers[i]->name();
					QCOMPARE(name, testCase.expectedEntries[i].name);
					QCOMPARE(map.contains(name), testCase.expectedEntries[i].mapContainsName);
					if(map.contains(name))
					{
						QCOMPARE(map[name], testCase.expectedEntries[i].isActivated);
					}

					else
					{
						QVERIFY(testCase.expectedEntries[i].isActivated);
					}
				}
			}
		}

		// NOLINTNEXTLINE(readability-convert-member-functions-to-static, *-function-cognitive-complexity)
		[[maybe_unused]] void testRemoveUnused()
		{
			using Lyrics::ServerEntry;
			struct TestCase
			{
				QList<Lyrics::ServerEntry> entries;
				QStringList expectedEntries;
			};

			const auto testCases = std::array {
				TestCase {
					{},
					QStringList {"Musixmatch", "Genius", "Sonichits"}
				},
				TestCase {
					{
						ServerEntry("Sonichits", true),
						ServerEntry("Genius", true),
						ServerEntry("Musixmatch", true),
					},
					QStringList {"Sonichits", "Genius", "Musixmatch"}
				},
				TestCase {
					{
						ServerEntry("Sonichits", false),
						ServerEntry("Genius", true),
						ServerEntry("Musixmatch", false)
					},
					QStringList {"Genius"}
				},

				TestCase {
					{
						ServerEntry("Sonichits", false),
						ServerEntry("Genius", false),
						ServerEntry("Musixmatch", false)
					},
					{}
				}
			};

			for(const auto& testCase: testCases)
			{
				SetSetting(Set::Lyrics_ServerEntries, testCase.entries);
				const auto servers = Lyrics::getSortedServerList(true, lyricConfigurationFile());
				const auto map = Lyrics::getActiveEntryMap();

				QCOMPARE(servers.count(), testCase.expectedEntries.count());

				for(int i = 0; i < servers.count(); i++)
				{
					const auto name = servers[i]->name();
					QCOMPARE(name, testCase.expectedEntries[i]);

					if(map.contains(name))
					{
						QCOMPARE(map[name], true);
					}
				}
			}
		}
};

QTEST_GUILESS_MAIN(LyricsServerProviderTest)

#include "LyricsServerProviderTest.moc"
