#include "variables_database.h"
#include "SH_server_base.h"
#include <QDebug>


SHSHistoryDatabaseBase::SHSHistoryDatabaseBase(): QThread() {
	is_run = is_ready = false;
}


SHSHistoryDatabaseBase::~SHSHistoryDatabaseBase() {
	stop();
}


void SHSHistoryDatabaseBase::start(QString filename) {
	stop();
	is_run = true;
	is_ready = false;
	db_filename = filename;
	start_tm.reset();
	QThread::start();
	while (elapsedStartTM() < start_timeout) {
		if (is_ready)
			break;
		piMSleep(10);
	}
	if (!is_ready) {
		qDebug() << "[SHSHistoryDatabaseBase] Error: can`t init database!";
		stop();
		return;
	}
}


void SHSHistoryDatabaseBase::stop() {
	if (!isRunning()) return;
	is_run = is_ready = false;
	if (!wait(stop_timeout * 1000))
		terminate();
}


void SHSHistoryDatabaseBase::setVariables(const QList<SHSHistoryDatabaseBase::Variable> & vars) {
	init_vars = vars;
	var_by_id.clear();
	for (const auto & v: vars)
		var_by_id[v.id] = v;
}


void SHSHistoryDatabaseBase::add(int id, qint64 t, double value) {
	add_mutex.lock();
	add_queue[id] << (HistoryRow){id, value, t};
	add_mutex.unlock();
}


void SHSHistoryDatabaseBase::readHistoryTick() {
	resetStartTM();
	emit readHistoryProgress();
}


void SHSHistoryDatabaseBase::resetStartTM() {
	tm_mutex.lock();
	start_tm.reset();
	tm_mutex.unlock();
}


double SHSHistoryDatabaseBase::elapsedStartTM() {
	tm_mutex.lock();
	double ret = start_tm.elapsed_s();
	tm_mutex.unlock();
	return ret;
}


void SHSHistoryDatabaseBase::run() {
	bool ok = init(db_filename, init_vars);
	if (!ok) {
		is_run = false;
		return;
	}
	qDebug() << "[SHSHistoryDatabaseBase] Reading history ...";
	emit readHistoryRequest();
	qDebug() << "[SHSHistoryDatabaseBase] Reading history done";
	is_ready = true;
	PITimeMeasurer tm;
	PISet<int> vars_to_clean;
	while (is_run) {
		if (tm.elapsed_s() >= clean_timeout) {
			if (!vars_to_clean.isEmpty()) {
				auto vcit = vars_to_clean.makeIterator();
				transaction();
				while (vcit.next())
					removeOldRows(vcit.key());
				commit();
				vars_to_clean.clear();
			}
			tm.reset();
		}
		add_mutex.lock();
		auto cq = add_queue;
		add_queue.clear();
		add_mutex.unlock();
		if (cq.isEmpty()) {
			piMSleep(100);
			continue;
		}
		transaction();
		auto cqit = cq.makeIterator();
		while (cqit.next()) {
			writeRows(cqit.key(), cqit.value());
			vars_to_clean << cqit.key();
		}
		commit();
		piMSleep(100);
	}
	destroy();
}
