/*
 * Copyright (C) 2014-2024 CZ.NIC
 *
 * 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/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QCoreApplication>
#include <QTime>

#include "src/gui/dlg_wait_progress.h"

/* Increment value in milliseconds. */
#define INCR_MS 20

DlgWaitProgress::DlgWaitProgress(int ms, const QString &text, QWidget *parent)
    : QProgressDialog(parent),
    m_timer()
{
	setMinimum(0);
	setMaximum(ms);
	setValue(0);
	setLabelText(text);

	connect(this, SIGNAL(canceled()), this, SLOT(stopTimer()));
	connect(&m_timer, SIGNAL(timeout()), this, SLOT(incrementProgress()));

	m_timer.start(INCR_MS);
}

/*!
 * @brief The function won't freeze the GUI.
 *
 * @param[in] ms Waiting time in milliseconds.
 */
static
void delay(int ms)
{
	if (Q_UNLIKELY(ms < 0)) {
		return;
	}

	QTime dieTime = QTime::currentTime().addMSecs(ms);
	while (QTime::currentTime() < dieTime) {
		QCoreApplication::processEvents(QEventLoop::AllEvents, INCR_MS);
	}
}

bool DlgWaitProgress::wait(int ms, const QString &text, QWidget *parent)
{
	/* Ignore negative values. */
	if (Q_UNLIKELY(ms < 0)) {
		return true;
	}
	/*
	 * Don't show the progress dialogue when waiting a short time in which
	 * the user is unlikely to react.
	 */
	if (Q_UNLIKELY(ms < 500)) {
		delay(ms);
		return true;
	}

	return (DlgWaitProgress(ms, text, parent).exec() == QDialog::Accepted);
}

void DlgWaitProgress::incrementProgress(void)
{
	int val = value();
	val += INCR_MS;
	if (val < maximum()) {
		setValue(val);
	} else {
		m_timer.stop();
		accept();
	}
}

void DlgWaitProgress::stopTimer(void)
{
	m_timer.stop();
}
