/* CoverConnector.cpp */

/* Copyright (C) 2011-2024 Michael Lugmair (Lucio Carreras)
 *
 * 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 "CoverConnector.h"
#include "Query.h"
#include "Utils/Utils.h"
#include "Utils/Set.h"

DB::Covers::Covers(const QString& connectionName) :
	DB::Module(connectionName) {}

DB::Covers::~Covers() = default;

bool DB::Covers::exists(const QString& hash)
{
	auto q = runQuery(
		QStringLiteral("SELECT hash FROM covers WHERE hash = :hash;"),
		{
			{QStringLiteral(":hash"), hash}
		},
		QStringLiteral("Cannot check cover"));

	if(hasError(q))
	{
		return false;
	}

	return q.next();
}

bool DB::Covers::getCover(const QString& hash, QPixmap& pm)
{
	auto q = runQuery(
		QStringLiteral("SELECT data FROM covers WHERE hash = :hash;"),
		{
			{QStringLiteral(":hash"), hash}
		},
		QStringLiteral("Cannot fetch cover"));

	if(hasError(q))
	{
		return false;
	}

	if(q.next())
	{
		const auto data = q.value(0).toByteArray();
		pm = ::Util::convertByteArrayToPixmap(data);

		return true;
	}

	return false;
}

bool DB::Covers::setCover(const QString& hash, const QPixmap& pm)
{
	if(hash.isEmpty() || pm.isNull())
	{
		return false;
	}

	if(this->exists(hash))
	{
		return updateCover(hash, pm);
	}

	else
	{
		return insertCover(hash, pm);
	}
}

bool DB::Covers::updateCover(const QString& hash, const QPixmap& pm)
{
	const auto data = ::Util::convertPixmapToByteArray(pm);
	const auto q = update(QStringLiteral("covers"),
	                      {{QStringLiteral("data"), data}},
	                      {QStringLiteral("hash"), hash},
	                      QStringLiteral("Cannot update cover"));

	return wasUpdateSuccessful(q);
}

bool DB::Covers::insertCover(const QString& hash, const QPixmap& pm)
{
	const auto data = ::Util::convertPixmapToByteArray(pm);
	const auto q = insert(QStringLiteral("covers"),
	                      {
		                      {QStringLiteral("data"), data},
		                      {QStringLiteral("hash"), hash}
	                      }, QStringLiteral("Cannot insert cover"));

	return !hasError(q);
}

bool DB::Covers::removeCover(const QString& hash)
{
	const auto q = runQuery(
		QStringLiteral("DELETE from covers WHERE hash=:hash;"),
		{{QStringLiteral(":hash"), hash}},
		QStringLiteral("Cannot delete cover %1").arg(hash));

	return !hasError(q);
}

Util::Set<QString> DB::Covers::getAllHashes()
{
	auto q = runQuery(QStringLiteral("SELECT hash FROM covers;"), QStringLiteral("Cannot fetch all hashes"));
	if(hasError(q))
	{
		return {};
	}

	Util::Set<QString> ret;
	while(q.next())
	{
		ret.insert(q.value(0).toString());
	}

	return ret;
}

bool DB::Covers::getAllCovers(QMap<QString, QPixmap>& covers)
{
	covers.clear();

	auto q = runQuery(QStringLiteral("SELECT hash, data FROM covers;"), QStringLiteral("Cannot fetch all covers"));
	if(hasError(q))
	{
		return false;
	}

	while(q.next())
	{
		const auto hash = q.value(0).toString();
		const auto data = q.value(1).toByteArray();

		covers[hash] = ::Util::convertByteArrayToPixmap(data);
	}

	return true;
}

void DB::Covers::clear()
{
	runQuery(QStringLiteral("DELETE FROM covers;"), QStringLiteral("Cannot drop all covers"));
}
