#include "configurationpage.h"
#include "ui_configurationpage.h"
#include <QScrollBar>

#include "connectandenterpage.h"

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

    connect( ui->pbLinkSerialNumber          , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosSerialNumber          ); } );
    connect( ui->pbLinkConfiguration         , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosConfiguration         ); } );
    connect( ui->pbLinkSoc                   , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosSoc                   ); } );
    connect( ui->pbLinkRestrictions          , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosRestrictions          ); } );
    connect( ui->pbLinkCellsConfiguration    , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosCellsConfiguration    ); } );
    connect( ui->pbLinkBalancingConfiguration, &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosBalancingConfiguration); } );
    connect( ui->pbLinkOutputsSetting        , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosOutputsSetting        ); } );
    connect( ui->pbLinkClaibrateZero         , &QPushButton::clicked, this, [=]() { setPositionInPixelsToScrollTo(PosClaibrateZero         ); } );

    connect( ui->pbReadDefaultSettingsFromFile , &QPushButton::clicked, this, &ConfigurationPage::onPbReadDefaultSettingsFromFileClicked);
    connect( ui->pbReadCurrentSettingsFromBms  , &QPushButton::clicked, this, &ConfigurationPage::onPbReadCurrentSettingsFromBmsClicked);
    connect( ui->pbWriteCurrentValuesToBms     , &QPushButton::clicked, this, &ConfigurationPage::onPbWriteCurrentValuesToBmsClicked);
    connect( ui->pbWriteToNonVolatileBmsMemory , &QPushButton::clicked, this, &ConfigurationPage::onPbWriteToNonVolatileBmsMemoryClicked);

    connect(ui->bmsSettings, &BmsSettings::showStatusInfo, this, &ConfigurationPage::showStatusInfo);
    connect(ui->bmsSettings, &BmsSettings::showMessageDialog, this, &ConfigurationPage::showMessageDialog);
    connect(ui->bmsSettings, &BmsSettings::sendMessage, this, &ConfigurationPage::sendMessage);
    connect(this, &ConfigurationPage::loadParams, ui->bmsSettings, &BmsSettings::onLoadParams);

    initTimerForStatusBar();
    initTimerForProgressBar();
    initTimerForOneSecondDelayAfterButtonClick();

    checkIfButtonTextFitsInButton();
}


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

void ConfigurationPage::setDieBieMS(BMSInterface *dieBieMS)
{
    mDieBieMS = dieBieMS;
    ui->bmsSettings->setDieBieMS(mDieBieMS);

    // SEND_STATUS_INFO //
    connect(mDieBieMS, &BMSInterface::statusMessage, this, &ConfigurationPage::showStatusInfo);

    connect(mDieBieMS->bmsConfig(), &ConfigParams::updateRequested, ui->bmsSettings, &BmsSettings::onBmsconfUpdateRequested);
    connect(mDieBieMS->bmsConfig(), &ConfigParams::updateRequestDefault, ui->bmsSettings, &BmsSettings::onBmsconfUpdateRequestDefault);
    connect(mDieBieMS->bmsConfig(), &ConfigParams::updated, ui->bmsSettings, &BmsSettings::onBmsconfUpdated);
    connect(mDieBieMS->bmsConfig(), &ConfigParams::updated, this, &ConfigurationPage::onBmsconfUpdatedOrStored);
    connect(mDieBieMS->bmsConfig(), &ConfigParams::stored, ui->bmsSettings, &BmsSettings::onBmsconfStored);
    connect(mDieBieMS->bmsConfig(), &ConfigParams::stored, this, &ConfigurationPage::onBmsconfUpdatedOrStored);

    //connect(mDieBieMS->bmsConfig(), &ConfigParams::updated, this, &ConfigurationPage::bmsconfUpdated);

    //void ConfigParams::requestUpdate()        => emit updateRequested();
    //void ConfigParams::requestUpdateDefault() => emit updateRequestDefault();
    //void ConfigParams::updateDone() =>  emit updated();
    //void ConfigParams::storingDone() => emit stored();

    //void sigBmsconfUpdateRequested();
    //void sigBmsconfUpdateRequestDefault();
    //void sigBmsconfUpdated();
    //void sigBmsconfStored();

    //connect(ui->bmsSettings, &BmsSettings::sendMessage, this, &ConfigurationPage::sendMessage);
    //connect(this, &ConfigurationPage::loadParams, ui->bmsSettings, &BmsSettings::onLoadParams);

    /*
    connect(mPacket, (dataToSend(QByteArray&)),this, (packetDataToSend(QByteArray&)));
    connect(mPacket, (packetReceived(QByteArray&)),this, (packetReceived(QByteArray&)));
    connect(mCommands, (dataToSend(QByteArray&)),this, (cmdDataToSend(QByteArray&)));
    connect(mCommands, (fwVersionReceived(int,int,QString,QByteArray)),this, SLOT(fwVersionReceived(int,int,QString,QByteArray)));
    connect(mCommands, (ackReceived(QString)), this, (ackReceived(QString)));
    connect(mbmsConfig, (updated()), this, (bmsconfUpdated()));
    connect(mbmsConfig, (stored()), this, (bmsconfStored()));
    connect(mTimer, (timeout()), this, (timerSlot()));
    */

}

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

void ConfigurationPage::checkIfButtonTextFitsInButton()
{
    int textWidth = QFontMetrics(ui->pbWriteCurrentValuesToBms->font()).width(ui->pbWriteCurrentValuesToBms->text());
    int btnWidth = ui->pbWriteCurrentValuesToBms->width();
    if(btnWidth <= textWidth)
        ui->pbWriteCurrentValuesToBms->setText(tr("Записать текущие значения\nв BMS"));
}

void ConfigurationPage::setPositionInPixelsToScrollTo(int positionInPixelsToScrollTo)
{
    if(positionInPixelsToScrollTo != PosSerialNumber)
        positionInPixelsToScrollTo -= 15;

    ui->scrollAreaBmsSettings->verticalScrollBar()->setValue(positionInPixelsToScrollTo);
}



//void ConfigurationPage::bmsconfUpdated()
//{
//    //mMcConfRead = false;
//}


#if 0
void ConfigurationPage::onTimerSlot()
{
    // Update status label
    if (mStatusInfoTime) {
        mStatusInfoTime--;
        if (!mStatusInfoTime) {
            //mStatusLabel->setStyleSheet(qApp->styleSheet());
        }
    }
    /*else {
        QString str = mDieBieMS->getConnectedPortName();
        if (str != mStatusLabel->text()) {
            mStatusLabel->setText(mDieBieMS->getConnectedPortName());
            static QString statusLast = "";
            if (str != statusLast) {
                mPageDebugPrint->printConsole("Status: " + str + "<br>");
                statusLast = str;
            }
        }
    }*/

/*    // CAN fwd
    if (ui->actionCanFwd->isChecked() != mDieBieMS->commands()->getSendCan()) {
        ui->actionCanFwd->setChecked(mDieBieMS->commands()->getSendCan());
    }

    // RT data only every 5 iterations
    if (ui->actionRtData->isChecked()) {
        static int values_cnt = 0;
        static int cells_cnt  = 0;

        values_cnt++;
        if (values_cnt >= 5) {
            values_cnt = 0;
            mDieBieMS->commands()->getValues();
        }

        cells_cnt++;
        if (cells_cnt >= 20) {
            cells_cnt = 0;
            mDieBieMS->commands()->getCells();
        }
    }

    // Send alive command once every 10 iterations
    if (ui->actionSendAlive->isChecked()) {
        static int alive_cnt = 0;
        alive_cnt++;
        if (alive_cnt >= 10) {
            alive_cnt = 0;
            mDieBieMS->commands()->sendAlive();
        }
    }
*/
    // Read configuration it isn't read since starting VESC Tool
    if (mDieBieMS->isPortConnected()) {
        static int conf_cnt = 0;
        conf_cnt++;
        if (conf_cnt >= 20) {
            conf_cnt = 0;
            if (!mMcConfRead) {
                mDieBieMS->commands()->getBMSconf();
                mMcConfRead = true;
            }
        }
    }

/*    // Disable all data streaming when uploading firmware
    if (mDieBieMS->commands()->getFirmwareUploadProgress() > 0.1) {
        ui->actionSendAlive->setChecked(false);
        ui->actionRtData->setChecked(false);
    }

    // Run startup checks
    static bool has_run_start_checks = false;
    if (!has_run_start_checks) {
        has_run_start_checks = true;
        checkUdev();
        Utility::checkVersion(mDieBieMS);
    }
*/



}
#endif



/*
{
// connect(mTimer, SIGNAL(timeout()),this, SLOT(timerSlot()));
connect(mDieBieMS, &BMSInterface::statusMessage, this, &ConnectAndEnterPage::showStatusInfo);
connect(mDieBieMS, &BMSInterface::messageDialog, this, &ConnectAndEnterPage::showMessageDialog);
connect(mDieBieMS, &BMSInterface::serialPortNotWritable, this, &ConnectAndEnterPage::serialPortNotWritable);
connect(mDieBieMS->commands(), &Commands::bmsConfigCheckResult, this, &ConnectAndEnterPage::bmsConfigCheckResult);
// connect(ui->actionAboutQt, SIGNAL(triggered(bool)),qApp, SLOT(aboutQt()));

// Remove the menu with the option to hide the toolbar
// ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);

mDieBieMS->bmsConfig()->loadParamsXml("://res/config.xml");
mDieBieMS->infoConfig()->loadParamsXml("://res/info.xml");
// reloadPages();

connect(mDieBieMS->bmsConfig(), SIGNAL(updated()), this, SLOT(bmsconfUpdated()));
}
//*/


void ConfigurationPage::onTimerSlot()
{
    // Update status label
    if (mStatusInfoTime) {
        mStatusInfoTime--;
        if (!mStatusInfoTime) {
            // clear Status Label
            ui->lbStatus->setText("");
            ui->lbStatus->setStyleSheet(qApp->styleSheet());
        }
    }
}

void ConfigurationPage::showStatusInfo(QString info, bool isGood)
{
    if (isGood) {
        ui->lbStatus->setStyleSheet("QLabel { background-color : lightgreen; color : black; }");
        mPageDebugPrint->printConsole("Status: " + info + "<br>");
    } else {
        ui->lbStatus->setStyleSheet("QLabel { background-color : red; color : black; }");
        mPageDebugPrint->printConsole("<font color=\"red\">Status: " + info + "</font><br>");
    }

    mStatusInfoTime = 160;
    ui->lbStatus->setText(info);
}


// pbLoadSettingsFromFile
//void ConfigurationPage::on_pbLoadSettingsFromFile_clicked()
//{
//    bool NOTHING_IS_CONNECTED_HERE_ACCORDING_SPECIFICATION_FROM_CUSTOMER = true;
//}


//// pbLoadCurrentSettingsFromBms
//void ConfigurationPage::on_pbLoadCurrentSettingsFromBms_clicked()
//{
//    // Загрузить настройки из файла
//    // Загрузить текущие настройки\nиз BMS
//    // actionReadBMScconf
//    mDieBieMS->commands()->getBMSconf();
//    // ? // mDieBieMS->commands()->getBMSconfDefault();
//}

//// pbWriteToNonVolatileBmsMemory
//void ConfigurationPage::on_pbWriteToNonVolatileBmsMemory_clicked()
//{
//    // Записать в энергонезависимую\nпамять BMS
//    // actionStoreBMScconf
//    mDieBieMS->commands()->storeBMSConfig();
//}

// pbWriteCurrentValuesToBms


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

/*
 start  0  12 = Default that is not in bms it's in somekind of real offline file (we do NOT have connection to bms but there parameters show up somehow)
connect 8  8 Config updated with default params not from file, but from default params of bms
    deflt bms  edit | bms edit
^  -  8    8     7  |   8    8 read bms conf
-> -  8    7     7  |   7    8 read default 8 is defaul - that was on the start
v  -  8    8     7  |   7    7 write bms config
S  -  8    ?     ?  |   ?    ? save currect config from bms into outside file to the flash card
           before   |   after
*/


void ConfigurationPage::onPbReadDefaultSettingsFromFileClicked()
{
    if(mIsOneSedondPassed)
    {
        mOneSecondWait->start();
        mIsOneSedondPassed = false;
        if(mIsOperationFinished)
        {
            mIsOperationFinished = false;

            onStartPercents();
            //     bms  edit | bms edit
            //-> -   7     7 |   7    8 read default 8 is defaul - that was on the start
            // Загрузить настройки\nпо умолчанию
            mDieBieMS->commands()->getBMSconfDefault();
        }
    }
}

void ConfigurationPage::onPbReadCurrentSettingsFromBmsClicked()
{
    if(mIsOneSedondPassed)
    {
        mOneSecondWait->start();
        mIsOneSedondPassed = false;

        if(mIsOperationFinished)
        {
            mIsOperationFinished = false;

            onStartPercents();
            //     bms  edit | bms edit
            //^  -   7     8 |   7    7 read bms conf
            mDieBieMS->commands()->getBMSconf();
        }
    }
}

//// pbLoadCurrentSettingsFromBms
void ConfigurationPage::onPbWriteCurrentValuesToBmsClicked()
{
    if(mIsOneSedondPassed)
    {
        mOneSecondWait->start();
        mIsOneSedondPassed = false;

        if(mIsOperationFinished)
        {
            mIsOperationFinished = false;

            onStartPercents();
            // Записать текущие значения в BMS
            // actionWriteBMScconf
            mDieBieMS->commands()->setBMSconf();
        }
    }
}

//// pbWriteToNonVolatileBmsMemory
void ConfigurationPage::onPbWriteToNonVolatileBmsMemoryClicked()
{
    if(mIsOneSedondPassed)
    {
        mOneSecondWait->start();
        mIsOneSedondPassed = false;

        if(mIsOperationFinished)
        {
            mIsOperationFinished = false;

            onStartPercents();
            // Записать в энергонезависимую\nпамять BMS
            // actionStoreBMScconf
            mDieBieMS->commands()->storeBMSConfig();
        }
    }
}


/*
void ConfigurationPage::onPbReadDefaultSettingsFromFileClicked()
{
    //     bms  edit | bms edit
    //-> -   7     7 |   7    8 read default 8 is defaul - that was on the start
    // Загрузить настройки\nпо умолчанию
    mDieBieMS->commands()->getBMSconfDefault();
}

void ConfigurationPage::onPbReadCurrentSettingsFromBmsClicked()
{
    //     bms  edit | bms edit
    //^  -   7     8 |   7    7 read bms conf
    mDieBieMS->commands()->getBMSconf();
}

//// pbLoadCurrentSettingsFromBms
void ConfigurationPage::onPbWriteCurrentValuesToBmsClicked()
{
    // Записать текущие значения в BMS
    // actionWriteBMScconf
    mDieBieMS->commands()->setBMSconf();
}

//// pbWriteToNonVolatileBmsMemory
void ConfigurationPage::onPbWriteToNonVolatileBmsMemoryClicked()
{
    // Записать в энергонезависимую\nпамять BMS
    // actionStoreBMScconf
    mDieBieMS->commands()->storeBMSConfig();
}
*/





//
//
//

void ConfigurationPage::onBmsconfUpdatedOrStored()
{
    mIsOperationFinished = true;
    //onFinishPercents();
}

void ConfigurationPage::initTimerForStatusBar()
{
    mTimer = new QTimer(this);
    connect(mTimer, &QTimer::timeout, this, &ConfigurationPage::onTimerSlot);
    mTimer->start(20);
}

void ConfigurationPage::initTimerForProgressBar()
{
    mTimerProgress = new QTimer(this);
    mTimerProgress->setSingleShot(false);
    mTimerProgress->setInterval(100);
    connect(mTimerProgress, &QTimer::timeout, this, &ConfigurationPage::processPercents);
    // timer->start(1000);
    ui->progressBar->setValue(0);
}

void ConfigurationPage::initTimerForOneSecondDelayAfterButtonClick()
{
    mOneSecondWait = new QTimer(this);
    mOneSecondWait->setSingleShot(true);
    mOneSecondWait->setInterval(10000);
    connect(mOneSecondWait, &QTimer::timeout, this, [this]()
    {
        mIsOneSedondPassed = true;
    });
    mIsOneSedondPassed = true;
    mIsOperationFinished = true;
}

void ConfigurationPage::processPercents()
{
    mSeconds++;
    int percents = mSeconds * (100.0 / mMaxSecs);
    ui->progressBar->setValue(percents);

    auto val = ui->progressBar->value();
    if (val >= 0 && val < 50)
    {
        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color:lime; };");
    }
    else if (val >= 50 && val < 85)
    {
        if(mIsOperationFinished)
        {
            mIsOneSedondPassed = true;
            mIsOperationFinished = true;

            onStopPercents();
        }

        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color:yellow; };");
    }
    else if (val >= 85 && val < 95)
    {
        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color:red; };");
    }
    else if (val >= 95)
    {
        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color:red; };");
        mIsOneSedondPassed = true;
        mIsOperationFinished = true;

        onStopPercents();
        showStatusInfo("ERROR! SOMETHING WENT WRONG", false);
    }

    //if (ui->progressBar->value() == 100)
    //    onFinishPercents();
}

void ConfigurationPage::onStartPercents()
{
    onStopPercents();
    mTimerProgress->start();
}

void ConfigurationPage::onStopPercents()
{
    mSeconds = 0;
    mTimerProgress->stop();
    ui->progressBar->setValue(0);

    //mIsOneSedondPassed = true;
    //mIsOperationFinished = true;
}

void ConfigurationPage::onFinishPercents()
{
    mTimerProgress->stop();
    mSeconds = 0;
    ui->progressBar->setValue(100);
}



















