/* StyleSettings.cpp, (Created on 10.11.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 "StyleSettings.h"
#include "VisualStyleTypes.h"

#include "Database/Connector.h"
#include "Database/VisualStyles.h"
#include "Utils/Algorithm.h"
#include "Utils/Logger/Logger.h"
#include "Utils/Language/Language.h"

#include <QMap>

#include <optional>

namespace
{
	RawColorStyle createEmptyStyle()
	{
		auto emptyStyle = RawColorStyle {};
		for(int i = 0; i < 4; i++)
		{
			emptyStyle.colorList.colors << QColor(0, 0, 0, 0);
		}

		return emptyStyle;
	}

	QList<RawColorStyle> prependEmptyStyle(QList<RawColorStyle> styles)
	{
		styles.push_front(createEmptyStyle());
		return styles;
	}
}

struct StyleSettings::Private
{
	DB::VisualStyles* db {DB::Connector::instance()->visualStyleConnector()};
	QList<RawColorStyle> styles {prependEmptyStyle(db->getRawColorStyles())};
	std::optional<RawColorStyle> temporaryStyle {std::nullopt};
	int currentIndex {-1};
};

StyleSettings::StyleSettings(QObject* parent) :
	QObject(parent),
	m {Pimpl::make<Private>()} {}

StyleSettings::~StyleSettings() = default;

void StyleSettings::select(const int index) { m->currentIndex = index; }

int StyleSettings::currentIndex() const { return m->currentIndex; }

QString StyleSettings::nameProposal() const
{
	auto names = QStringList {};
	Util::Algorithm::transform(m->styles, names, [](const auto& style) {
		return style.colorList.name;
	});

	for(int i = 1; i < 100; i++) // NOLINT(*-magic-numbers)
	{
		const auto newName = QString("%1 %2")
			.arg(Lang::get(Lang::New))
			.arg(i);

		if(!names.contains(newName, Qt::CaseInsensitive))
		{
			return newName;
		}
	}

	return {};
}

QList<RawColorStyle> StyleSettings::styles() const { return m->styles; }

std::optional<RawColorStyle> StyleSettings::currentStyle() const { return style(m->currentIndex); }

std::optional<RawColorStyle> StyleSettings::style(const int index) const
{
	return (index >= 0) && (index < m->styles.count())
	       ? std::optional {m->styles[index]}
	       : std::nullopt;
}

int StyleSettings::count() const { return m->styles.count(); }

bool StyleSettings::saveCurrent(const RawColorStyle& style)
{
	if((m->currentIndex < 0) || (m->currentIndex >= m->styles.count()))
	{
		return false;
	}

	const auto name = style.colorList.name;
	if(name.isEmpty())
	{
		return false;
	}

	spLog(Log::Info, this) << "Save values to " << name;
	const auto success = (m->db->rawColorStyleExists(name))
	                     ? m->db->updateRawColorStyle(style)
	                     : m->db->insertRawColorStyle(style);

	if(success)
	{
		m->styles = prependEmptyStyle(m->db->getRawColorStyles());
		emit sigStylesChanged();
	}

	return success;
}

bool StyleSettings::deleteCurrent()
{
	if((m->currentIndex < 0) || (m->currentIndex >= m->styles.count()))
	{
		return false;
	}

	const auto success = m->db->deleteRawColorStyle(m->styles[m->currentIndex].colorList.name);
	if(success)
	{
		m->styles = prependEmptyStyle(m->db->getRawColorStyles());
		emit sigStylesChanged();
	}

	return success;
}
