#include <QDebug>
#include <QSettings>

#include "MathProvider.h"

static QString getExpressionSettingKey(int index) {

    static const QString prefix = QString("data/math_equations/");

    return prefix + QString::number(index);
}

static QString getUnitSettingKey(int index) {

    static const QString prefix = QString("data/math_equations_units/");

    return prefix + QString::number(index);
}

MathProvider::MathProvider() : TProvider("MATH") {}

MathProvider::~MathProvider() {

    // Singleton lives forever! No kidding, it gets killed like anyone else.
    // Even immortal objects can't escape garbage collection.
}

int MathProvider::getDeviceCount() { return mathChannels.size(); }

QVector<TDevice *> MathProvider::getDevices() {

    const int n = mathChannels.size();

    QVector<TDevice *> devices(n);
    for (int i = 0; i < n; i++) {
        devices[i] = mathChannels[i]->getDevice();
    }

    return devices;
}

TDevice *MathProvider::findDevice(const QString &serialNumber) {

    return nullptr; // unimplemented
}

int MathProvider::start() {

    if (started) {
        return 1;
    }

    started = true;

    QSettings settings;
    uint n = settings.value("data/num_math_channels", 4).toUInt();

    mathChannels.resize(n);

    for (int i = 0; i < n; i++) {

        MathChannel *mc = new MathChannel(i);
        mathChannels[i] = mc;

        connect(mc, &QThread::finished, mc, &QObject::deleteLater);

        unit_t unit = settings.value(getUnitSettingKey(i)).toUInt();
        QString expression = settings.value(getExpressionSettingKey(i)).toString();

        mc->setUnit(unit);
        mc->setExpression(expression);

        mathChannels[i]->start();
    }

    return 0;
}

void MathProvider::shutdown() {

    if (!started) {
        return;
    }

    started = false;

    for (int i = 0; i < mathChannels.size(); i++) {
        mathChannels[i]->shutdown();
    }

    mathChannels.clear();
}

void MathProvider::setPollInterval(int ms) {

    // nothing to do
}

void MathProvider::setVirtualOptions(unsigned int flags, double slp) {

    // nothing to do
}

void MathProvider::setUserCalibration(const QString &serialNumber, int channelIndex, bool on) {

    // nothing to do
}

void MathProvider::setExpression(int index, const QString &expression) {

    if (index < 0 || index >= mathChannels.size()) {
        return;
    }

    QSettings settings;
    settings.setValue(getExpressionSettingKey(index), expression);

    mathChannels[index]->setExpression(expression);
}

void MathProvider::setUnit(int index, unit_t unit) {

    if (index < 0 || index >= mathChannels.size()) {
        return;
    }

    QSettings settings;
    settings.setValue(getUnitSettingKey(index), unit);

    mathChannels[index]->setUnit((int)unit);
}

QString MathProvider::getExpression(int index) const {

    if (index < 0 || index >= mathChannels.size()) {
        return QString();
    }

    return mathChannels[index]->getExpression();
}

unit_t MathProvider::getUnit(int index) const {

    if (index < 0 || index >= mathChannels.size()) {
        return UNIT_UNKNOWN;
    }

    return mathChannels[index]->getUnit();
}
