/* VersionChecker.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 "VersionChecker.h"

#include "Utils/WebAccess/WebClientImpl.h"
#include "Utils/Message/Message.h"
#include "Utils/Logger/Logger.h"
#include "Utils/Settings/Settings.h"
#include "Utils/Utils.h"

#include <QCheckBox>
#include <QDialogButtonBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QFrame>

struct VersionChecker::Private
{
	QWidget* parent;

	explicit Private(QWidget* parent) :
		parent{parent} {}
};

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

VersionChecker::~VersionChecker() = default;

void VersionChecker::start()
{
	const auto url = QStringLiteral("https://sayonara-player.com/current_version");

	auto* webClient = new WebClientImpl(this);
	connect(webClient, &WebClient::sigFinished, this, &VersionChecker::versionCheckFinished);

	webClient->run(url);
}

void VersionChecker::versionCheckFinished()
{
	auto* webClient = dynamic_cast<WebClient*>(sender());

	const auto status = webClient->status();
	const auto data = webClient->data();

	webClient->deleteLater();

	if(status != WebClient::Status::GotData || data.isEmpty())
	{
		return;
	}

	const auto newVersion = QString(data).trimmed();
	const auto currentVersion = GetSetting(Set::Player_Version);

	spLog(Log::Info, this) << "Newest Version: " << newVersion;
	spLog(Log::Info, this) << "This Version:   " << currentVersion;

	if(Util::Version::fromString(currentVersion) < Util::Version::fromString(newVersion))
	{
		auto* dialog = new GUI_NewVersionDialog(currentVersion, newVersion, m->parent);
		connect(dialog, &Gui::Dialog::sigClosed, this, [dialog, this] {
			emit sigFinished();
			dialog->deleteLater();
		});

		dialog->open();
		return;
	}

	emit sigFinished();
}

GUI_NewVersionDialog::GUI_NewVersionDialog(const QString& currentVersion, const QString& newVersion, QWidget* parent):
	Dialog(parent) {
	setWindowTitle(tr("New Version Available"));

	auto* layout = new QVBoxLayout(this);
	layout->setContentsMargins(10, 10, 10, 10); // NOLINT(*-magic-numbers)
	layout->setSpacing(5); // NOLINT(*-magic-numbers)

	auto* labMessage = new QLabel(tr("A new version is available!"), this);
	labMessage->setAlignment(Qt::AlignCenter);
	labMessage->setWordWrap(true);

	auto* labVersions = new QLabel(
		tr("Your version: %1 — New version: %2").arg(currentVersion, newVersion), this);
	labVersions->setAlignment(Qt::AlignCenter);

	const auto versionString = QString(
		R"(<a href="https://sayonara-player.com">https://sayonara-player.com</a>)");
	auto* labLink = new QLabel(versionString, this);
	labLink->setOpenExternalLinks(true);
	labLink->setAlignment(Qt::AlignCenter);

	auto* line = new QFrame(this);
	line->setFrameShape(QFrame::HLine);
	line->setFrameShadow(QFrame::Sunken);

	m_cbDontNotify = new QCheckBox(tr("Don't notify me about new versions"), this);
	m_cbDontNotify->setChecked(!GetSetting(Set::Player_NotifyNewVersion));

	auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, this);

	layout->addWidget(labMessage);
	layout->addWidget(labVersions);
	layout->addWidget(labLink);
	layout->addWidget(line);
	layout->addWidget(m_cbDontNotify);
	layout->addWidget(buttonBox);

	connect(m_cbDontNotify, &QCheckBox::toggled, this, [](const auto checked) {
		SetSetting(Set::Player_NotifyNewVersion, !checked);
	});

	connect(buttonBox, &QDialogButtonBox::accepted, this, &GUI_NewVersionDialog::close);
}
