/*
    QAD - Qt ADvanced

    Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef qad_timers_H
#define qad_timers_H

#include "qad_utils_export.h"

#include <QDebug>
#include <QMap>
#include <QTimer>
#include <pisystemtime.h>


template<typename Index = int>
class QAD_UTILS_EXPORT IndexedTimer {
public:
	~IndexedTimer() { stopAllIndexedTimers(); }

	void setIndexedTimerType(Index index, Qt::TimerType type) { timers[index].type = type; }
	void setIndexedTimerSingleShot(Index index, bool yes) { timers[index].single_shot = yes; }
	void bindIndexedTimer(Index index, std::function<void()> func) { timers[index].func = func; }
	void stopAllIndexedTimers() {
		for (auto & i: timers)
			i.destroy();
		timers.clear();
	}
	void stopIndexedTimer(Index index) {
		auto & t(timers[index]);
		if (!t.isValid()) return;
		t.destroy();
	}
	void startIndexedTimer(Index index, PISystemTime interval, std::function<void()> func = nullptr) {
		stopIndexedTimer(index);
		__TimerSlot & t(timers[index]);
		if (func) t.func = func;
		if (!t.func) {
			qDebug() << "[IndexedTimer] startIndexedTimer error: null function!";
			return;
		}
		t.timer = new QTimer();
		t.timer->setTimerType(t.type);
		t.timer->setSingleShot(t.single_shot);
		QObject::connect(t.timer, &QTimer::timeout, t.func);
		t.timer->start(interval.toMilliseconds());
	}
	bool isIndexedTimerStarted(Index index) const { return timers.value(index).isValid(); }
	PISystemTime indexedTimerRemainingTime(Index index) const {
		const __TimerSlot & t(timers[index]);
		if (!t.timer) return {};
		int ms = t.timer->remainingTime();
		if (ms < 0) return {};
		return PISystemTime::fromMilliseconds(ms);
	}

private:
	struct __TimerSlot {
		bool isValid() const { return timer; }
		void destroy() {
			if (!timer) return;
			delete timer;
			timer = nullptr;
		}
		std::function<void()> func = nullptr;
		QTimer * timer             = nullptr;
		bool single_shot           = false;
		Qt::TimerType type         = Qt::CoarseTimer;
	};

	QMap<Index, __TimerSlot> timers;
};


#endif
