#include "BatteryController.h"

#include <QDateTime>
#include <QDebug>
#include <QTimer>

#include <bitset>

BatteryController::BatteryController(QObject *parent)
	: QObject{parent}
{
}

BatteryController::~BatteryController()
{
}

int BatteryController::batteryIndex() const
{
	return batteryIndex_;
}

void BatteryController::setBatteryIndex(int index)
{
	if (batteryIndex_ == index)
		return;

	batteryIndex_ = index;
	emit batteryIndexChanged();
}

int BatteryController::chargeType() const
{
	return chargeType_;
}

void BatteryController::setChargeType(int type)
{
	if (chargeType_ == type)
		return;

	chargeType_ = type;
	emit chargeTypeChanged();
}

int BatteryController::workingMode() const
{
	return workingMode_;
}

void BatteryController::setWorkingMode(int mode)
{
	if (workingMode_ == mode)
		return;

	workingMode_ = mode;
	emit workingModeChanged();
}

QVariant BatteryController::controlVoltage() const
{
	return controlVoltage_;
}

void BatteryController::setControlVoltage(const QVariant& value)
{
	if (controlVoltage_ == value)
		return;

	controlVoltage_ = value;
	emit controlVoltageChanged();
}

QVariant BatteryController::controlCurrent() const
{
	return controlCurrent_;
}

void BatteryController::setControlCurrent(const QVariant& value)
{
	if (controlCurrent_ == value)
		return;

	controlCurrent_ = value;
	emit controlCurrentChanged();
}

QVariant BatteryController::controlTemperature() const
{
	return controlTemperature_;
}

void BatteryController::setControlTemperature(const QVariant& value)
{
	if (controlTemperature_ == value)
		return;

	controlTemperature_ = value;
	emit controlTemperatureChanged();
}

QVariant BatteryController::controlCapacity() const
{
	return controlCapacity_;
}

void BatteryController::setControlCapacity(const QVariant& value)
{
	if (controlCapacity_ == value)
		return;

	controlCapacity_ = value;
	emit controlCapacityChanged();
}

QVariant BatteryController::measuredVoltage() const
{
	return measuredVoltage_;
}

void BatteryController::setMeasuredVoltage(const QVariant& value)
{
	if (measuredVoltage_ == value)
		return;

	measuredVoltage_ = value;
	emit measuredVoltageChanged();
}

QVariant BatteryController::measuredCurrent() const
{
	return measuredCurrent_;
}

void BatteryController::setMeasuredCurrent(const QVariant& value)
{
	if (measuredCurrent_ == value)
		return;

	measuredCurrent_ = value;
	emit measuredCurrentChanged();
}

QVariant BatteryController::measuredTemperature() const
{
	return measuredTemperature_;
}

void BatteryController::setMeasuredTemperature(const QVariant& value)
{
	if (measuredTemperature_ == value)
		return;

	measuredTemperature_ = value;
	emit measuredTemperatureChanged();
}

QVariant BatteryController::measuredCapacity() const
{
	return measuredCapacity_;
}

void BatteryController::setMeasuredCapacity(const QVariant& value)
{
	if (measuredCapacity_ == value)
		return;

	measuredCapacity_ = value;
	emit measuredCapacityChanged();
}

QVariantList BatteryController::statuses() const
{
	return statuses_;
}

void BatteryController::setStatuses(const QVariantList& statuses)
{
	if (statuses_ == statuses)
		return;

	statuses_ = statuses;
	emit statusesChanged();
}

void BatteryController::addStatus(const quint32 status)
{
	QVariantList statusList;
	auto appendStatus = [&statusList](const QVariant& subStatus)
	{
		statusList.append(subStatus);
	};

	QMap<qsizetype, QVariantList> statusBitDescriptions =
	{
		{0, {"Ошибка Т датчика БК", StatusSeverity::Error}},
		{1, {"Глубокий разряд АКБ", StatusSeverity::Error}},
		{2, {"Заряд выполнен", StatusSeverity::Info}},
		{3, {"Ошибка Т датчика УКПБ", StatusSeverity::Info}},

		{4, {"Ток долго не снижается", StatusSeverity::Error}},
		{5, {"Ошибка БПС3000", StatusSeverity::Error}},
		{6, {"U менее 61.25 В", StatusSeverity::Error}},
		{7, {"U выше нормы", StatusSeverity::Error}},

		{8, {"Первичный подзаряд завершен", StatusSeverity::Info}},
		{9, {"Разряд завершен", StatusSeverity::Info}},
		{10, {"Повторный заряд завершен", StatusSeverity::Info}},
		{11, {"Более 45 гр. °С", StatusSeverity::Warning}},

		{12, {"Разночтение в токах", StatusSeverity::Error}},
		{13, {"Разночтение в напряжениях", StatusSeverity::Error}},
		{14, {"Разночтение в температурах", StatusSeverity::Error}},
		{15, {"Разночтение в емкости АКБ", StatusSeverity::Info}},

		{16, {"Низкий разряд АКБ", StatusSeverity::Info}},
		{17, {"Ошибка контрольного заряда", StatusSeverity::Error}},
		{18, {"УКПБ не подключен", StatusSeverity::Warning}},
		{19, {"БК не подключен", StatusSeverity::Warning}}
	};

	for (auto it = statusBitDescriptions.constBegin(); it != statusBitDescriptions.constEnd(); ++it)
	{
		if (status & (1 << it.key()))
		{
			appendStatus(it.value());
		}
	}

	if (statusList.isEmpty())
	{
		appendStatus(QVariantList{"Штатный режим", StatusSeverity::Info});
	}

	statuses_.clear();

	for (const auto& statusVariant: statusList)
	{
		const auto statusDescription = statusVariant.toList();
		if (statusDescription.size() < 2)
		{
			continue;
		}

		QVariantMap statusMap;
		statusMap.insert("time", QDateTime::currentDateTime().toString("hh:mm:ss dd-MM-yyyy"));
		statusMap.insert("status", "0x" + QString::number(status, 16).toUpper().rightJustified(8, '0'));
		statusMap.insert("description", statusDescription.at(0));
		statusMap.insert("severity", statusDescription.at(1));

		statuses_.append(statusMap);
	}

	emit statusesChanged();
}
