// SPDX-License-Identifier: GPL-3.0-or-later
/*
 * Qt mutizone MQTT thermostat
 *
 * Copyright (C) 2019 Richard Genoud
 *
 */

#include <QTranslator>
#include <QSettings>
#include <QString>
#include <QDebug>

#include "settings.h"

const char default_room_names[MAX_NB_ZONES][42] = {
	"Bedroom",
	"Living Room",
	"Workspace",
	"Bathroom"
};

const char default_sensors_topics[MAX_NB_ZONES][64] = {
	"sensors/bedroom/xiaomi",
	"sensors/living_room/xiaomi",
	"sensors/workspace/xiaomi",
	"sensors/bathroom/xiaomi"
};

const char default_availability_topics[MAX_NB_ZONES][64] = {
	"sensors/bedroom/availability",
	"sensors/living_room/availability",
	"sensors/workspace/availability",
	"sensors/bathroom/availability"
};

const char default_control_topics[MAX_NB_ZONES][64] = {
	"heaters/bedroom",
	"heaters/living_room",
	"heaters/workspace",
	"heaters/bathroom"
};

Settings *Settings::_singleton = NULL;

Settings::Settings(QObject *parent) : QSettings(parent)
{
	struct Room room;
	struct Heater heater;
	struct Program program;
	int nb_rooms;

	m_state = OFF;

	QString st = this->value("state", "off").toString();
	if (st.compare(QString("on"), Qt::CaseInsensitive) == 0) {
		m_state = ON;
	}
	if (st.compare(QString("auto"), Qt::CaseInsensitive) == 0) {
		m_state = AUTO;
	}

	m_end_holiday = QDateTime::fromString(this->value("end_holiday",
							  "2020-01-01T00:00:00Z").toString(),
					      Qt::ISODate);
	if (!m_end_holiday.isValid()) {
		m_end_holiday = QDateTime::currentDateTime();
	}

	nb_rooms = this->beginReadArray("rooms");
	if (nb_rooms == 0) {
		this->endArray();
		set_rooms_default_config();
		nb_rooms = this->beginReadArray("rooms");
	}

	if (nb_rooms > MAX_NB_ZONES) {
		// TODO;
		nb_rooms = MAX_NB_ZONES;
	}

	// TODO: handle unset values in a better way
	for (int i = 0; i < nb_rooms; ++i) {
		this->setArrayIndex(i);
		room.name = this->value("name", default_room_names[i]).toString();
		room.sensor_topic = this->value("sensor_topic", default_sensors_topics[i]).toString();
		room.availability_topic = this->value("availability_topic",
						      default_availability_topics[i]).toString();
		int size = this->beginReadArray("heaters");
		for (int j = 0; j < size; ++j) {
			this->setArrayIndex(j);
			heater.ctrl_topic = this->value("control_topic", "").toString();
			room.heaters << heater;
		}
		this->endArray();
		room.default_temperature = this->value("default_temperature", 20).toDouble();
		size = this->beginReadArray("temperature_schedule");
		for (int j = 0; j < size; ++j) {
			/* TODO: check for overlapping schedules ? */
			this->setArrayIndex(j);
			program.temperature = this->value("temperature", 20).toDouble();
			program.DoW = this->value("days_of_week", 127).toInt();
			program.start_time = QTime::fromString(this->value("start_time", "").toString(), "H:m");
			program.end_time = QTime::fromString(this->value("end_time", "").toString(), "H:m");
			if (program.start_time.isValid() && program.end_time.isValid() &&
			    (program.DoW > 0) && (program.DoW < 128)) {
				room.progs << program;
			}
		}
		this->endArray();
		m_rooms << room;
		room.progs.clear();
		room.heaters.clear();
	}
	this->endArray();
	m_broker.address = this->value("broker/address", "localhost").toString();
	m_broker.port = this->value("broker/port", 1883).toInt();
}

void Settings::setPowerState(enum power_states state)
{
	switch (state) {
	case OFF:
		m_state = OFF;
		this->setValue("state", "off");
		break;
	case ON:
		m_state = ON;
		this->setValue("state", "on");
		break;
	case AUTO:
		m_state = AUTO;
		this->setValue("state", "auto");
		break;
	default:
		/* TODO: error */
		break;
	}
}

void Settings::setEndHoliday(const QDateTime &endDate)
{
	if (endDate.isValid()) {
		m_end_holiday = endDate;
		this->setValue("end_holiday", m_end_holiday.toString(Qt::ISODate));
	}
	/* else TODO: error */
}

void Settings::set_rooms_default_config(void)
{
	this->setValue("state", "auto");
	this->beginWriteArray("rooms");

	for (int i = 0; i < MAX_NB_ZONES; i++) {
		this->setArrayIndex(i);
		this->setValue("name", tr(default_room_names[i]));
		this->setValue("sensor_topic", default_sensors_topics[i]);
		this->setValue("availability_topic", default_availability_topics[i]);
		this->setValue("default_temperature", 20);
		this->beginWriteArray("heaters");
		this->setArrayIndex(0);
		this->setValue("control_topic", default_control_topics[i]);
		this->endArray();
	}

	this->setArrayIndex(0);
	this->beginWriteArray("temperature_schedule");
	this->setArrayIndex(0);
	this->setValue("temperature", 18);
	this->setValue("days_of_week", 127);
	this->setValue("start_time", QTime(22,0).toString("H:m"));
	this->setValue("end_time", QTime(7,0).toString("H:m"));
	this->endArray();


	this->setArrayIndex(3);
	this->beginWriteArray("temperature_schedule");
	this->setArrayIndex(0);
	this->setValue("temperature", FORCE_ON);
	this->setValue("days_of_week", 31);
	this->setValue("start_time", QTime(6,30).toString("H:m"));
	this->setValue("end_time", QTime(7,0).toString("H:m"));
	this->setArrayIndex(1);
	this->setValue("temperature", FORCE_ON);
	this->setValue("days_of_week", 96);
	this->setValue("start_time", QTime(7,30).toString("H:m"));
	this->setValue("end_time", QTime(8,0).toString("H:m"));
	this->endArray();

	this->endArray();
	this->sync();
}

int Settings::nbZones(void)
{
	return m_rooms.size();
}

Settings::~Settings(void)
{
}

Settings *Settings::getInstance(void)
{
	if (!_singleton) {
		_singleton =  new Settings();
	}

	return _singleton;
}

/* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */


