/* LyricsServerProvider.cpp, (Created on 15.05.2024) */

/* 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 "LyricServer.h"
#include "LyricServerJsonWriter.h"
#include "LyricsServerProvider.h"

#include "Utils/Algorithm.h"
#include "Utils/LyricServerEntry.h"
#include "Utils/Settings/Settings.h"
#include "Utils/StandardPaths.h"

#include <QDir>

namespace Lyrics
{
	namespace
	{
		QList<Server*> addServer(Server* server, QList<Server*> servers)
		{
			if(!server || (!server->canFetchDirectly() && !server->canSearch()))
			{
				return servers;
			}

			const auto name = server->name();
			const auto index = Util::Algorithm::indexOf(servers, [&](auto* s) {
				return (s->name() == name);
			});

			const auto found = (index >= 0);
			if(found)
			{
				servers.replace(index, server);
			}

			else
			{
				servers << server;
			}

			return servers;
		}

		QList<Server*> initCustomServers(QList<Server*> servers)
		{
			const auto lyricsPath = Util::lyricsPath();
			const auto dir = QDir(lyricsPath);
			const auto jsonFiles = dir.entryList(QStringList {"*.json"}, QDir::Files);

			for(auto jsonFile: jsonFiles)
			{
				jsonFile.prepend(lyricsPath + "/");
				auto customServers = Lyrics::ServerJsonReader::parseJsonFile(jsonFile);
				for(auto* customServer: customServers)
				{
					servers = addServer(customServer, std::move(servers));
				}
			}

			return servers;
		}

		QHash<QString, Server*> convertServersToMap(const QList<Server*>& servers)
		{
			auto result = QHash<QString, Server*> {};
			for(auto* server: servers)
			{
				result[server->name()] = server;
			}

			return result;
		}
	}

	QList<Server*> parseServers(const QString& filename)
	{
		// motörhead
		// crosby, stills & nash
		// guns 'n' roses
		// AC/DC
		// the doors
		// the rolling stones
		// petr nalitch
		// eric burdon and the animals
		// Don't speak

		auto result = QList<Server*> {};
		const auto servers = Lyrics::ServerJsonReader::parseJsonFile(filename);
		for(auto* server: servers)
		{
			result = addServer(server, std::move(result));
		}

		return initCustomServers(std::move(result));
	}

	QList<Server*> getSortedServerList(const bool removeUnchecked, const QString& filename)
	{
		const auto servers = parseServers(filename);
		auto entryMap = getActiveEntryMap();
		auto serverMap = convertServersToMap(servers);
		auto result = QList<Server*> {};

		const auto entries = GetSetting(Set::Lyrics_ServerEntries);
		for(const auto& entry: entries)
		{
			if(serverMap.contains(entry.name))
			{
				result << serverMap[entry.name];
			}
		}

		for(auto* server: servers)
		{
			if(!entryMap.contains(server->name()))
			{
				result << server;
			}
		}

		if(removeUnchecked)
		{
			Util::Algorithm::removeIf(result, [&](auto* server) {
				return entryMap.contains(server->name()) && (entryMap[server->name()] == false);
			});
		}

		return result;
	}

	QHash<QString, bool> getActiveEntryMap()
	{
		const auto entries = GetSetting(Set::Lyrics_ServerEntries);

		auto result = QHash<QString, bool> {};
		for(const auto& entry: entries)
		{
			result[entry.name] = entry.isChecked;
		}

		return result;
	}

	QString defaultLyricConfiguration() { return ":/lyrics/lyrics.json"; }

} // Lyrics