#include "akbmonitorpage.h"
#include "ui_akbmonitorpage.h"

#include <QIntValidator>
#include <QDoubleValidator>
#include <QDateTime>
#include <math.h>

#include "configparamsgetter.h"

AkbMonitorPage::AkbMonitorPage(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::AkbMonitorPage)
{
    ui->setupUi(this);

    ui->pbLoadDataFromBmsMemory->hide();

    // L
    ui->lbCellNumberLeft->hide();
    ui->lbCellNumberLeftDots->hide();
    ui->editCellNumberLeft->hide();
    // R
    ui->lbCellNumberRight->hide();
    ui->lbCellNumberRightDots->hide();
    ui->editCellNumberRight->hide();

    // 1 // L
    ui->editBatteryChargeLevel  ->setValidator( new QIntValidator(-1000, 1000, this) ); // mValues.soC
    ui->editBatteryVoltage      ->setValidator( new QIntValidator(-1000, 1000, this) ); // mValues.packVoltage
    ui->editNominalCapacity     ->setValidator( new QIntValidator(-1000, 1000, this) ); //, mDieBieMS->bmsConfig(), "batteryCapacity");
    ui->editBatteryTemperature  ->setValidator( new QDoubleValidator(-100, 100, 2, this) ); // mValues.tempBattHigh
    // 1 // R
    ui->editModulesNumber       ->setValidator( new QIntValidator(-1000, 1000, this) ); //, mDieBieMS->bmsConfig(), "cellMonitorICCount");
    ui->editCellsNumber         ->setValidator( new QIntValidator(-1000, 1000, this) ); //, mDieBieMS->bmsConfig(), "noOfCellsSeries");
    ui->editActualCapacity      ->setValidator( new QIntValidator(-1000, 1000, this) ); // NOT IN SETTINGS
    ui->editBmsTemperature      ->setValidator( new QDoubleValidator(-100, 100, 2, this) ); // mValues.tempBMSHigh
    //
    // 2 // L                   ->clear();
    ui->editMaxVoltageOnCell    ->setValidator( new QDoubleValidator(-100, 100, 2, this) ); // mValues.cVHigh
    ui->editCellNumberLeft      ->setValidator( new QIntValidator(-1000, 1000, this) ); // NOT IN SETTINGS
    ui->editCircuit             ->setValidator( new QIntValidator(-1000, 1000, this) ); // mValues.packCurrent
    // 2 // R                   ->clear();
    ui->editMinVoltageOnCell    ->setValidator( new QDoubleValidator(-100, 100, 2, this) ); // mValues.cVLow
    ui->editCellNumberRight     ->setValidator( new QIntValidator(-100, 1000, this) ); // NOT IN SETTINGS


    mTimer = new QTimer(this);
    mTimer->start(1000);

    connect(mTimer, &QTimer::timeout,this, &AkbMonitorPage::timerSlot);

    clearControlls();
}

AkbMonitorPage::~AkbMonitorPage()
{
    delete ui;
}




BMSInterface *AkbMonitorPage::bms() const
{
    return mDieBieMS;
}

void AkbMonitorPage::setDieBieMS(BMSInterface *dieBieMS)
{
    mDieBieMS = dieBieMS;

    if (mDieBieMS) {
        connect(mDieBieMS->commands(), &Commands::valuesReceived,this, &AkbMonitorPage::valuesReceived);
        //connect(mDieBieMS->commands(), &Commands::cellsReceived,this, &VisualizationPage::cellsReceived);
        connect(mDieBieMS->bmsConfig(), &ConfigParams::updated, this, &AkbMonitorPage::onLoadParams);
    }
}


void AkbMonitorPage::timerSlot()
{
    //
    // We will start revieve Data WHEN
    // SEE - void MainWindowNew::onTimerSlot()
    // one of those left-tab-bar buttons are selected (ui->pbMainMenuBarVisualization->isChecked() || ui->pbMainMenuBarVisualization->isChecked())
    //

    //////////////////////////////////////////////////////////////////////////////////////

    // 1 // L
    if(!mSoc.empty())
        ui->editBatteryChargeLevel->setText(QString::number(mSoc.last()));          // mValues.soC

    if(!mPackVoltage.empty()) {
        //ui->editBatteryVoltage->setText(QString::number(mPackVoltage.last()));      // mValues.packVoltage
        ui->editBatteryVoltage->setText(QString::number(mPackVoltage.last(), 'f', 2));  // mValues.packVoltage
    }

    //addParamRow(ui->editNominalCapacity, mDieBieMS->bmsConfig(), "batteryCapacity");

    //////////////////////////////////////////////////////////////////////////////////////

    if(!mTempBattHigh.empty())
        ui->editBatteryTemperature->setText(QString::number((int)mTempBattHigh.last()));  // mValues.tempBattHigh
        //ui->editBatteryTemperature->setText(QString::number(mTempBattHigh.last(), 'f', 2));  // mValues.tempBattHigh

    // 1 // R
    //addParamRow(ui->editModulesNumber, mDieBieMS->bmsConfig(), "cellMonitorICCount");
    //addParamRow(ui->editCellsNumber, mDieBieMS->bmsConfig(), "noOfCellsSeries");
    //// ui->editActualCapacity   // NOT IN SETTINGS // AND NOT IN BMS_VALUES - valuesReceived(BMS_VALUES values)
    if(!mTempBMSHigh.empty())
        ui->editBmsTemperature->setText(QString::number((int)mTempBMSHigh.last()));  // mValues.tempBMSHigh
        //ui->editBmsTemperature->setText(QString::number(mTempBMSHigh.last(), 'f', 2));       // mValues.tempBMSHigh

    //////////////////////////////////////////////////////////////////////////////////////

    // 2 // L
    if(!mCellVHigh.empty())
        ui->editMaxVoltageOnCell->setText(QString::number(mCellVHigh.last(), 'f', 2));      // mValues.cVHigh

    //// ui->editCellNumberLeft   // NOT IN SETTINGS // AND NOT IN BMS_VALUES - valuesReceived(BMS_VALUES values)

    if(!mPackCurrent.empty())
        ui->editCircuit->setText(QString::number(mPackCurrent.last()));             // mValues.packCurrent
    // 2 // R

    if(!mCellVLow.empty())
        ui->editMinVoltageOnCell->setText(QString::number(mCellVLow.last(), 'f', 2));       // mValues.cVLow

    //// ui->editCellNumberRight  // NOT IN SETTINGS // AND NOT IN BMS_VALUES - valuesReceived(BMS_VALUES values)

    //////////////////////////////////////////////////////////////////////////////////////

    //if (mUpdateValPlot)
    //{
        /*
        int dataSize = mPackVoltage.size();

        QVector<double> xAxis(dataSize);
        for (int i = 0;i < mSeconds.size();i++) {
            xAxis[i] = mSeconds[i];
        }
        */

        /*
        // Current and duty-plot
        ///int graphIndex = 0;
        ///ui->ivLCGraph->graph(graphIndex++)->setData(xAxis, mPackVoltage);
        ///ui->ivLCGraph->graph(graphIndex++)->setData(xAxis, mLCLoadVoltage);
        ///ui->ivLCGraph->graph(graphIndex++)->setData(xAxis, mLCLoadCurrent);

        ///graphIndex = 0;
        ///ui->ivHCGraph->graph(graphIndex++)->setData(xAxis, mHCLoadVoltage);
        ///ui->ivHCGraph->graph(graphIndex++)->setData(xAxis, mHCLoadCurrent);

        ///graphIndex = 0;
        ///ui->cellGraph->graph(graphIndex++)->setData(xAxis, mCellVHigh);
        ///ui->cellGraph->graph(graphIndex++)->setData(xAxis, mCellVAverage);
        ///ui->cellGraph->graph(graphIndex++)->setData(xAxis, mCellVLow);

        ///graphIndex = 0;
        ///mTempBMSLow.fill(0,1);
        ///ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBMSHigh);
        ///ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBMSAverage);
        ///ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBMSLow);
        */

        // V
        /*
        double valVMax = mHCLoadVoltage.last();
        double valVMid = mPackVoltage.last();
        double valVMin = mLCLoadVoltage.last();
        */
        /*// increas X
        chartV->appendNextX();
        // then set all new Ys
        chartV->appendYToSeries(VoltageMax, valVMax);
        chartV->appendYToSeries(VoltageMid, valVMid);
        chartV->appendYToSeries(VoltageMin, valVMin);

        ui->lbVMaxLegendVal->setText(QString("%1").arg(valVMax));
        ui->lbVMidLegendVal->setText(QString("%1").arg(valVMid));
        ui->lbVMinLegendVal->setText(QString("%1").arg(valVMin));

        chartV->update();
        ui->chartViewVoltage->repaint();
        */

        // A
        /*
        double valAMax = mHCLoadCurrent.last();
        double valAMid = mMCLoadCurrent_.last();
        double valAMin = mLCLoadCurrent.last();
        */
        /*// increas X
        chartA->appendNextX();
        // then set all new Ys
        chartA->appendYToSeries(AmperageMax, valAMax);
        chartA->appendYToSeries(AmperageMid, valAMid);
        chartA->appendYToSeries(AmperageMin, valAMin);

        ui->lbAMaxLegendVal->setText(QString("%1").arg(valAMax));
        ui->lbAMidLegendVal->setText(QString("%1").arg(valAMid));
        ui->lbAMinLegendVal->setText(QString("%1").arg(valAMin));

        chartA->update();
        ui->chartViewAmperage->repaint();
        */

        // T
        /*
        double valTMax = mTempBattHigh.last();
        double valTMid = mTempBattAverage.last();
        double valTMin = mTempBattLow_.last();
        */
        /*mTempBattLow_.fill(0,1);
        // increas X
        chartT->appendNextX();
        // then set all new Ys
        chartT->appendYToSeries(TemperatureMax, valTMax);
        chartT->appendYToSeries(TemperatureMid, valTMid);
        chartT->appendYToSeries(TemperatureMin, valTMin);

        ui->lbTMaxLegendVal->setText(QString("%1").arg(valTMax));
        ui->lbTMidLegendVal->setText(QString("%1").arg(valTMid));
        ui->lbTMinLegendVal->setText(QString("%1").arg(valTMin));

        chartT->update();
        ui->chartViewTemperature->repaint();
        */

        // C
        /*
        double valCMax = mCellVHigh.last();
        double valCMid = mCellVAverage.last();
        double valCMin = mCellVLow.last();
        */
        /*// increas X
        chartC->appendNextX();
        // then set all new Ys
        chartC->appendYToSeries(CellsMax, valCMax);
        chartC->appendYToSeries(CellsMid, valCMid);
        chartC->appendYToSeries(CellsMin, valCMin);

        ui->lbCMaxLegendVal->setText(QString("%1").arg(valCMax));
        ui->lbCMidLegendVal->setText(QString("%1").arg(valCMid));
        ui->lbCMinLegendVal->setText(QString("%1").arg(valCMin));

        chartC->update();
        ui->chartViewCells->repaint();
        */


        /*
        ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBattHigh);
        ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBattAverage);
        ui->tempGraph->graph(graphIndex++)->setData(xAxis, mTempBattLow);

        ///if (ui->autoscaleButton->isChecked())
        {
            ///ui->ivLCGraph->rescaleAxes();
            ///ui->ivHCGraph->rescaleAxes();
            ///ui->cellGraph->rescaleAxes();
            ui->tempGraph->rescaleAxes();
        }

        ///ui->ivLCGraph->replot();
        ///ui->ivHCGraph->replot();
        ///ui->cellGraph->replot();
        ui->tempGraph->replot();
        ///ui->cellBarGraph->replot();

        mUpdateValPlot = false;
        */
    //}
}


void AkbMonitorPage::valuesReceived(BMS_VALUES values)
{
    //ui->rtText->setValues(values);

    const int maxS = 500;

    appendDoubleAndTrunc(&mSoc, values.soC, maxS);
    appendDoubleAndTrunc(&mPackCurrent, values.packCurrent, maxS);
    appendDoubleAndTrunc(&mPackVoltage, values.packVoltage, maxS);

    appendDoubleAndTrunc(&mLCLoadVoltage, values.loadLCVoltage, maxS);
    appendDoubleAndTrunc(&mLCLoadCurrent, values.loadLCCurrent, maxS);

    appendDoubleAndTrunc(&mHCLoadVoltage, values.loadHCVoltage, maxS);
    appendDoubleAndTrunc(&mHCLoadCurrent, values.loadHCCurrent, maxS);

    appendDoubleAndTrunc(&mAuxVoltage, values.auxVoltage, maxS);
    appendDoubleAndTrunc(&mAuxCurrent, values.auxCurrent, maxS);

    appendDoubleAndTrunc(&mCellVHigh, values.cVHigh, maxS);
    appendDoubleAndTrunc(&mCellVAverage, values.cVAverage, maxS);
    appendDoubleAndTrunc(&mCellVLow, values.cVLow, maxS);

    appendDoubleAndTrunc(&mTempBMSHigh, values.tempBMSHigh, maxS);
    appendDoubleAndTrunc(&mTempBMSAverage, values.tempBMSAverage, maxS);
    //appendDoubleAndTrunc(&mTempBMSLow_, values.tempBMSLow_, maxS);

    appendDoubleAndTrunc(&mTempBattHigh, values.tempBattHigh, maxS);
    appendDoubleAndTrunc(&mTempBattAverage, values.tempBattAverage, maxS);
    //appendDoubleAndTrunc(&mTempBattLow_, values.tempBattLow_, maxS);


    qint64 tNow = QDateTime::currentMSecsSinceEpoch();

    double elapsed = (double)(tNow - mLastUpdateTime) / 1000.0;
    if (elapsed > 1.0) {
        elapsed = 1.0;
    }

    mSecondCounter += elapsed;

    appendDoubleAndTrunc(&mSeconds, mSecondCounter, maxS);

    mLastUpdateTime = tNow;

    mUpdateValPlot = true;
}

/*
void AkbMonitorPage::cellsReceived(int cellCount, QVector<double> cellVoltageArray)
{
    QVector<double> dataxNew;
    dataxNew.clear();
    QVector<double> datayNormal;
    datayNormal.clear();
    QVector<double> datayBalance;
    datayBalance.clear();
    QVector<QString> labels;
    int indexPointer;

    double cellHardUnder = mDieBieMS->bmsConfig()->getParamDouble("cellHardUnderVoltage");
    double cellHardOver  = mDieBieMS->bmsConfig()->getParamDouble("cellHardOverVoltage");

    for(indexPointer = 0; indexPointer < cellCount; indexPointer++){
        dataxNew.append(indexPointer + 1);

        if(cellVoltageArray[indexPointer] < 0.0){
            datayNormal.append(0.0);
            datayBalance.append(fabs(cellVoltageArray[indexPointer]));
        }else{
            datayNormal.append(fabs(cellVoltageArray[indexPointer]));
            datayBalance.append(0.0);
        }

        QString voltageString = QStringLiteral("%1V (C").arg(fabs(cellVoltageArray[indexPointer]), 0, 'f',3);
        labels.append(voltageString + QString::number(indexPointer) + ")");
    }

    //QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
    //textTicker->addTicks(dataxNew, labels);

    //ui->cellBarGraph->xAxis->setTicker(textTicker);
    //ui->cellBarGraph->xAxis->setRange(0.5, indexPointer + 0.5);
    //ui->cellBarGraph->yAxis->setRange(cellHardUnder, cellHardOver);
    //barsNormal->setData(dataxNew, datayNormal);
    //barsBalance->setData(dataxNew, datayBalance);
}
*/

void AkbMonitorPage::appendDoubleAndTrunc(QVector<double> *vec, double num, int maxSize)
{
    vec->append(num);

    if(vec->size() > maxSize) {
        vec->remove(0, vec->size() - maxSize);
    }
}



void AkbMonitorPage::clearControlls()
{
    // 1 // L
    ui->editBatteryChargeLevel  ->clear(); // mValues.soC
    ui->editBatteryVoltage      ->clear(); // mValues.packVoltage
    ui->editNominalCapacity     ->clear(); //, mDieBieMS->bmsConfig(), "batteryCapacity");
    ui->editBatteryTemperature  ->clear(); // mValues.tempBattHigh
    // 1 // R                   ->clear();
    ui->editModulesNumber       ->clear(); //, mDieBieMS->bmsConfig(), "cellMonitorICCount");
    ui->editCellsNumber         ->clear(); //, mDieBieMS->bmsConfig(), "noOfCellsSeries");
    ui->editActualCapacity      ->clear(); // NOT IN SETTINGS
    ui->editBmsTemperature      ->clear(); // mValues.tempBMSHigh
    //                          ->clear();
    // 2 // L                   ->clear();
    ui->editMaxVoltageOnCell    ->clear(); // mValues.cVHigh
    ui->editCellNumberLeft      ->clear(); // NOT IN SETTINGS
    ui->editCircuit             ->clear(); // mValues.packCurrent
    // 2 // R                   ->clear();
    ui->editMinVoltageOnCell    ->clear(); // mValues.cVLow
    ui->editCellNumberRight     ->clear(); // NOT IN SETTINGS
}

void AkbMonitorPage::onLoadParams()
{
    ///QHash<QString, ConfigParam> mParams;

    //addParamRow(ui->editPointZeroDetectorValue, mDieBieMS->bmsConfig(), "shuntLCFactor");
    //ui->specificationsTab->addRowSeparator(tr("Pack configuration"));

    // Серийный номер * //ui->editSerialNumber
    getSerialNumber(ui->editSerialNumber, mDieBieMS->bmsConfig(), "notUsedCurrentThreshold");
    // 1 // L
    // ui->editBatteryChargeLevel // mValues.soC
    // ui->editBatteryVoltage     // mValues.packVoltage
    addParamRow(ui->editNominalCapacity, mDieBieMS->bmsConfig(), "batteryCapacity");
    // ui->editBatteryTemperature // mValues.tempBattHigh
    // 1 // R
    addParamRow(ui->editModulesNumber, mDieBieMS->bmsConfig(), "cellMonitorICCount");
    addParamRow(ui->editCellsNumber, mDieBieMS->bmsConfig(), "noOfCellsSeries");
    //// ui->editActualCapacity   // NOT IN BMS_CONFIG
    // ui->editBmsTemperature     // mValues.tempBMSHigh

    // 2 // L
    // ui->editMaxVoltageOnCell   // mValues.cVHigh
    //// ui->editCellNumberLeft   // NOT IN BMS_CONFIG
    // ui->editCircuit            // mValues.packCurrent
    // 2 // R
    // ui->editMinVoltageOnCell   // mValues.cVLow
    //// ui->editCellNumberRight  // NOT IN BMS_CONFIG
}

/*
bool AkbMonitorPage::addParamRow(QLineEdit* edit, ConfigParams *params, QString paramName)
{
    bool res = false;
    QWidget *editor = params->getEditor(paramName);
    QString name = params->getLongName(paramName);

    if (editor) {
        //int row = rowCount();
        //setRowCount(row + 1);
        //QTableWidgetItem *item = new QTableWidgetItem(name);
        //item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        //setItem(row, 0, item);
        //setCellWidget(row, 1, editor);
        //edit->setText(editor->);

        auto vtype = editor->property("type");
        auto type = vtype.toInt();
        //CFG_T_UNDEFINED = 0,
        if(type == 1) // CFG_T_DOUBLE,
        {
            auto vval = editor->property("value");
            auto val = vval.toDouble();
            edit->setText(QString::number(val));
        }
        else if(type == 2) // CFG_T_INT,
        {
            auto vval = editor->property("value");
            auto val = vval.toInt();
            edit->setText(QString::number(val));
        }
        else if(type == 3) // CFG_T_QSTRING,
        {
            auto vval = editor->property("value");
            auto val = vval.toString();
            edit->setText(val);
        }
        else if(type == 4) // CFG_T_ENUM,
        {
            auto vval = editor->property("value");
            auto val = vval.toInt();
            edit->setText(QString::number(val));
        }
        else if(type == 5) // CFG_T_BOOL
        {
            auto vval = editor->property("value");
            auto val = vval.toBool();
            edit->setText(val ? "true" : "false");
        }

        auto vsuffix = editor->property("suffix");
        auto suffix = vsuffix.toString();
        auto veditorDecimalsDouble = editor->property("editorDecimalsDouble");
        auto editorDecimalsDouble = veditorDecimalsDouble.toDouble();
        auto veditAsPercentage = editor->property("editAsPercentage");
        auto editAsPercentage = veditAsPercentage.toBool();

        res = true;
        //resizeColumnToContents(0);
        //resizeRowsToContents();
    }

    return res;
}
//*/

