#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setupChart(ui->customPlot);
    connect(ui->actionSave_file_as,SIGNAL(triggered()),this,SLOT(saveFileAs()));
    connect(ui->actionLoad_file,SIGNAL(triggered()),this,SLOT(loadFile()));
    connect(ui->horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(horzScrollBarChanged(int)));
    connect(ui->actionOnly_panel, SIGNAL(triggered()), this, SLOT(resize_only_panel()));
    connect(ui->actionAll_settings, SIGNAL(triggered()), this, SLOT(resize_all_settings()));
    connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(connect_device()));
    connect(ui->actionNew_data, SIGNAL(triggered()), this, SLOT(new_data()));

    ui->horizontalScrollBar->setRange(0,0);
    //SET TIMER
    TimerAnimation = new QTimer(this);
    TimerValues = new QTimer(this);
    connect(TimerValues, SIGNAL(timeout()), this, SLOT(update_values()));
    connect(TimerAnimation, SIGNAL(timeout()), this, SLOT(replot_animation()));

    Device = new DeviceCom();

    //add label to statusbar
    statusConnect = new QLabel(this);
    statusConnect->setText("Disconnected");

    statusConnect->setStyleSheet("* { background-color: rgb(255, 89, 88);padding:2px; }");
    ui->statusBar->addPermanentWidget(statusConnect);
    ui->controlMode_CC->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");
    ui->controlMode_CV->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");



}

void MainWindow::horzScrollBarChanged(int value)
{
    ui->customPlot->xAxis->setRange( value, ( 10 + value ) );
    ui->customPlot->replot();
}


void MainWindow::setupChart( QCustomPlot *customPlot ){

    // create graph and assign data to it:
    customPlot->addGraph(customPlot->xAxis, customPlot->yAxis);
    customPlot->graph(0)->setPen(QPen(Qt::blue));
    customPlot->graph(0)->setLineStyle(QCPGraph::lsStepLeft);
    customPlot->graph(0)->setScatterStyle(QCPScatterStyle::ssCross);
    customPlot->graph(0)->setName("Voltage [V]");

    customPlot->addGraph(customPlot->xAxis, customPlot->yAxis2);
    customPlot->graph(1)->setPen(QPen(Qt::red));
    customPlot->graph(1)->setLineStyle(QCPGraph::lsStepLeft);
    customPlot->graph(1)->setScatterStyle(QCPScatterStyle::ssCross);
    customPlot->graph(1)->setName("Current [A]");

    customPlot->legend->setVisible(true);
    customPlot->legend->setFont(QFont("Helvetica",9));
    customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));

    customPlot->yAxis2->setVisible(true);

    customPlot->xAxis->setLabel("Time [s]");
    customPlot->yAxis->setLabel("Voltage [V]");
    customPlot->yAxis2->setLabel("Current [A]");

    customPlot->xAxis->setRange(0, 10);
    customPlot->xAxis->setAutoTickStep(false);
    customPlot->xAxis->setTickStep(1);

    customPlot->yAxis->setRange(0, 25);
    customPlot->yAxis->setAutoTickStep(false);
    customPlot->yAxis->setTickStep(5);

    customPlot->yAxis2->setRange(0, 2);
    customPlot->yAxis2->setAutoTickStep(false);
    customPlot->yAxis2->setTickStep(0.25);

    //ANIMATION GRAPH
    customPlot->addGraph();
    customPlot->graph(2)->setPen(QPen(Qt::green));
    customPlot->graph(2)->setBrush(QBrush(QColor(0, 255, 0, 40)));
    customPlot->graph(2)->setLineStyle(QCPGraph::lsStepLeft);
    customPlot->legend->removeItem(2);
    customPlot->replot();

}

MainWindow::~MainWindow()
{
    Device->disconnect();
    delete Device;
    delete TimerAnimation;
    delete TimerValues;
    delete ui;
}

void MainWindow::disconnect_device(){
    Device->disconnect();
    ui->run_button->setEnabled(false);
    ui->set_output->setEnabled(false);
    ui->actionConnect->setText("Connect");
    ui->statusBar->showMessage(tr("Disconnected"), 3000);
    statusConnect->setText("Disconnected");
    statusConnect->setStyleSheet("* { background-color: rgb(255, 89, 88);padding:2px; }");
    TimerValues->stop();
}


void MainWindow::on_add_button_clicked()
{
    int  rowCount;     //row count in data_table

    rowCount = ui->data_table->rowCount();

    //if not duplicate time
    for(int i = 0; i < rowCount; ++i) {
        if ( ui->data_table->item(i, 0)->text() == QString("%1").arg( ui->new_time->value() ) ) {
            return;
        }
    }

    QTableWidgetItem *dataTable = new QTableWidgetItem();

    ui->data_table->insertRow( rowCount );                          //insert new row

    dataTable->setData(Qt::EditRole,ui->new_time->value());         //kvuli shortu
    ui->data_table->setItem( rowCount, 0, dataTable );              //add time to row

    ui->data_table->setItem( rowCount, 1, new QTableWidgetItem( QString("%1").arg( ui->new_voltage->value() ).replace(".", ",") ) );    //add voltage to row
    ui->data_table->setItem( rowCount, 2, new QTableWidgetItem( QString("%1").arg( ui->new_current->value() ).replace(".", ",") ) );    //add current to row
    ui->data_table->sortItems(0,Qt::AscendingOrder);                //sort items

    //add to graph
    double time = (double)ui->new_time->value();
    ui->customPlot->graph(0)->addData( time, (double)ui->new_voltage->value() );
    ui->customPlot->graph(1)->addData( time, (double)ui->new_current->value() );

    if ( time > 10 ) {
        if ( !( ( rowCount > 0 ) && ( ( (int)time - 10 ) < ui->horizontalScrollBar->maximum() ) ) ) {
            ui->horizontalScrollBar->setRange(0,( time - 10 ) );
        }

        ui->horizontalScrollBar->setEnabled(true);
    }
    ui->customPlot->replot();

}

void MainWindow::on_delete_button_clicked()
{
    int  currentRow, key;
    currentRow = ui->data_table->currentRow();
    key = ui->data_table->item(currentRow,0)->text().toInt();

    if ( ui->data_table->selectionModel()->hasSelection() ) {
        ui->data_table->removeRow( currentRow );
    }
    if ( currentRow < ui->data_table->rowCount() ) {
        ui->data_table->selectRow( currentRow );
    } else {
        ui->data_table->selectRow( currentRow - 1 );
    }

    ui->customPlot->graph(0)->removeData(key);
    ui->customPlot->graph(1)->removeData(key);

    if ( ui->data_table->rowCount() > 0 ) {
        int maxVal = ui->data_table->item( ui->data_table->rowCount() - 1, 0)->text().toInt();

        if ( ui->horizontalScrollBar->maximum() == ( key - 10 ) ) {
             if ( ui->horizontalScrollBar->maximum() == ui->horizontalScrollBar->value() ) {
                 ui->customPlot->xAxis->setRange( maxVal - 10, maxVal );
             }
             ui->horizontalScrollBar->setRange(0, maxVal - 10 );
        }
    } else {
        ui->horizontalScrollBar->setEnabled(false);
        ui->customPlot->xAxis->setRange( 0, 10 );
    }
    ui->customPlot->replot();




}

void MainWindow::on_data_table_itemClicked()
{
    int  row,iItemValue;
    double dItemValue;

    row = ui->data_table->currentRow();

    iItemValue = ui->data_table->item(row,0)->text().toInt();
    ui->new_time->setValue( iItemValue );

    dItemValue = ui->data_table->item(row,1)->text().replace(",",".").toDouble();
    ui->new_voltage->setValue( dItemValue );

    dItemValue = ui->data_table->item(row,2)->text().replace(",",".").toDouble();
    ui->new_current->setValue( dItemValue );
}

void MainWindow::saveFileAs() {

    QString fileName;

    fileName = QFileDialog::getSaveFileName(this, "Save file", "", "CSV file (*.csv)");

    if ( fileName.isEmpty() ) {
        return;
    }

    QFile saveFile( fileName );
    if ( !saveFile.open( QIODevice::WriteOnly ) ) {
        QMessageBox messageBox;
        messageBox.critical(0,"Error","File could not be saved");
        messageBox.setFixedSize(500,200);
    }

    QTextStream data( &saveFile );
    QStringList strList;

    for (int col = 0; col < ui->data_table->columnCount(); ++col) {
        strList << "\"" + ui->data_table->horizontalHeaderItem(col)->data(Qt::DisplayRole).toString() + "\"";
    }
    data << strList.join(";") + "\n";

    for (int i = 0; i < ui->data_table->rowCount(); ++i) {
        strList.clear();
        for (int col = 0; col < ui->data_table->columnCount(); ++col) {
            strList << ui->data_table->item(i,col)->text();
        }
        data << strList.join(";") + "\n";
    }

    ui->statusBar->showMessage(tr("File saved successfully."), 3000);
}

void MainWindow::loadFile() {

    QString fileName;

    fileName = QFileDialog::getOpenFileName(this, "Open file", NULL, "CSV file (*.csv)");

    if ( fileName.isEmpty() ) {
        return;
    }

    QFile loadFile( fileName );
    if ( !loadFile.open( QIODevice::ReadOnly ) ) {
        QMessageBox messageBox;
        messageBox.critical(0,"Error","File could not be opened");
        messageBox.setFixedSize(500,200);
    }

    QString data;
    QStringList rowOfData;
    QStringList rowData;
    int rowCount;

    data = loadFile.readAll();
    rowOfData = data.split("\n");
    loadFile.close();

    new_data();

    for (int r = 0; r < rowOfData.size(); ++r) {
        rowData = rowOfData.at(r).split(";");
        if ( rowData.value(0)[0] != '\"' && ( !rowData.value(0).isEmpty() && !rowData.value(1).isEmpty() && !rowData.value(2).isEmpty() ) ) {
            rowCount = ui->data_table->rowCount();
            ui->data_table->insertRow( rowCount );
            QTableWidgetItem *dataTable = new QTableWidgetItem();
            dataTable->setData(Qt::EditRole,rowData.value(0).toInt());
            ui->data_table->setItem( rowCount, 0, dataTable );
            for (int i=1; i < rowData.size(); ++i) {
                ui->data_table->setItem( rowCount, i, new QTableWidgetItem( QString("%1").arg( rowData.value(i).replace(",",".").toDouble() ) ) );
            }

            //add to graph
            ui->customPlot->graph(0)->addData(rowData.value(0).toInt(), rowData.value(1).replace(",",".").toDouble());
            ui->customPlot->graph(1)->addData(rowData.value(0).toInt(), rowData.value(2).replace(",",".").toDouble());
        }
    }

    //replot graph
    ui->customPlot->replot();

    ui->data_table->sortItems(0,Qt::AscendingOrder);

    int maxTime =  ui->data_table->item( (ui->data_table->rowCount() - 1), 0)->text().toInt(); //max time value
    if ( maxTime > 10 ) {
            ui->horizontalScrollBar->setRange(0,( maxTime - 10 ) );
        ui->horizontalScrollBar->setEnabled(true);
    }

    ui->statusBar->showMessage(tr("File loaded successfully."), 3000);

}

void MainWindow::resize_only_panel() {
    this->setMinimumHeight(261);
    this->setMaximumHeight(261);
    this->setMinimumWidth(301);
    this->setMaximumWidth(301);
    this->setGeometry( this->geometry().x(), this->geometry().y(), 301, 261);
    ui->actionOnly_panel->setEnabled(false);
    ui->actionAll_settings->setChecked(false);
    ui->actionAll_settings->setEnabled(true);
}

void MainWindow::resize_all_settings() {
    this->setMinimumHeight(600);
    this->setMaximumHeight(600);
    this->setMinimumWidth(800);
    this->setMaximumWidth(800);
    this->setGeometry( this->geometry().x(), this->geometry().y(), 800, 600);
    ui->actionOnly_panel->setEnabled(true);
    ui->actionOnly_panel->setCheckable(false);
    ui->actionAll_settings->setEnabled(false);
}

void MainWindow::connect_device() {

    if ( ui->actionConnect->text() == "Disconnect" ) {
        disconnect_device();
    } else {

        int retConnect;
        retConnect = Device->connect();

        if ( retConnect != 0) {
            QMessageBox messageBox;
            messageBox.setFixedSize(500,200);
            switch(retConnect) {
                case 1:
                    messageBox.warning(0,"Warning","Device not found");
                    break;
                case 2:
                    messageBox.warning(0,"Warning","Devices could not be opened");
                    break;
                case 3:
                    messageBox.warning(0,"Warning","Set commucation Failed");
                    break;

            }

        }


        //start timer
        TimerValues->start(200);

        //Connected
        ui->actionConnect->setText("Disconnect");
        ui->run_button->setEnabled(true);
        ui->set_output->setEnabled(true);
        ui->statusBar->showMessage(tr("Connected"), 3000);
        statusConnect->setText("Connected");
        statusConnect->setStyleSheet("QWidget { background-color: rgb(129, 191, 71);padding:2px; }");



    }
}
void MainWindow::replot_animation() {
    if ( Device->checkDevice() != 0 || Device->isConnected() == false ) {
        disconnect_device();
        TimerAnimation->stop();

    } else {
    //    ui->lcdNumber->display();
        AnimationTime++;
        if ( AnimationTime > ui->data_table->item( (ui->data_table->rowCount() - 1), 0)->text().toInt() ) {
            TimerAnimation->stop();
            ui->customPlot->graph(2)->clearData();
            ui->customPlot->replot();
            ui->run_button->setEnabled(true);
            return;
        }

        //SET TO DEVICE

        //FIND ROW
        bool founded = false;
        int row = 0;
        for(int i = 0; i < ui->data_table->rowCount(); ++i) {
            if ( AnimationTime == ui->data_table->item( i, 0)->text().toInt() ) {
                founded = true;
                row = i;
            }
        }
        if (founded) {
            BYTE value;
            int ret;

            double voltage = ui->data_table->item(row,1)->text().replace(",",".").toDouble() * 10;
            value = (float)( voltage );

            ret = Device->setValue(1, value);

            if ( ret != 0 ) {
                ret = Device->setValue(1, value);
                if ( ret != 0 ) {
                    qDebug() << "error | animation_voltage(): Value has not been changed";
                    //TimerAnimation->stop();

                }
            }

            double current = ui->data_table->item(row,2)->text().replace(",",".").toDouble() * 100;
            value = (float)( current );

            ret = Device->setValue(2, value);

            if ( ret != 0 ) {
                ret = Device->setValue(2, value);
                if ( ret != 0 ) {
                    qDebug() << "error | animation_voltage(): Value has not been changed";
                    //TimerAnimation->stop();
                }
            }
        }

        ui->customPlot->graph(2)->clearData();
        ui->customPlot->graph(2)->addData(0, 25);
        ui->customPlot->graph(2)->addData(AnimationTime, 25);
        ui->customPlot->replot();
        if ( AnimationTime > 10 ) {
            ui->horizontalScrollBar->setValue(AnimationTime - 10);
        }
    }

}
void MainWindow::update_values() {

    BYTE newValues[4];
    int ret;

    if ( Device->checkDevice() != 0 || Device->isConnected() == false ) {
        disconnect_device();

    } else {

        ret = Device->getNewValues(newValues);
        switch(ret) {
            case 1:
                qDebug() << "Error | update_value(): UART Write failed";
                break;
            case 2:
                qDebug() << "Error | update_value(): UART Read failed";
                break;
            case 3:
                qDebug() << "Error | update_value(): Read string is bad ";
                break;

        }

        //voltage
        ui->lcdNumber->display( QString("%1").arg(newValues[0] / 10.0) );
        //current
        ui->lcdNumber_2->display( QString("%1").arg(newValues[1] / 100.0) );
        //controlMode
        switch ( newValues[2] ) {
            case 1:
                ui->controlMode_CV->setStyleSheet("QCheckBox::indicator { background-color: rgb(255, 0, 0);border-radius: 5px;border:1px solid black; }");
                ui->controlMode_CC->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");
                break;
            case 2:
                ui->controlMode_CV->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");
                ui->controlMode_CC->setStyleSheet("QCheckBox::indicator { background-color: rgb(255, 0, 0);border-radius: 5px;border:1px solid black; }");
                break;
            default:
                ui->controlMode_CV->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");
                ui->controlMode_CC->setStyleSheet("QCheckBox::indicator { background-color: rgb(200, 200, 200);border-radius: 5px;border:1px solid black; }");

        }
        if ( newValues[3] ) {
            ui->set_output->setText("Output OFF");
            ui->set_output->setChecked(true);
        } else {
            ui->set_output->setText("Output ON");
            ui->set_output->setChecked(false);
        }
    }



}

void MainWindow::on_run_button_clicked()
{
    if ( Device->isConnected() ) {
        ui->customPlot->graph(2)->clearData();
        TimerAnimation->start(1000);
        AnimationTime = 0;
        ui->run_button->setEnabled(false);
        ui->statusBar->showMessage(tr("Running"), ( ui->data_table->item( (ui->data_table->rowCount() - 1), 0)->text().toInt() + 1 ) * 1000);
   }
}


void MainWindow::on_stop_button_clicked() {
    TimerAnimation->stop();
    ui->customPlot->graph(2)->clearData();
    ui->customPlot->replot();
    ui->run_button->setEnabled(true);
    ui->statusBar->showMessage(tr("Running stoped"), 3000);
}
void MainWindow::new_data() {

    if ( ui->data_table->rowCount() > 0 ) {
        QMessageBox msgBox;
        msgBox.setText("Do you want to save current data?");
//        msgBox.setInformativeText("Do you want to save your changes?");
        msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        msgBox.setDefaultButton(QMessageBox::Save);
        int msgRet = msgBox.exec();
        switch( msgRet ) {
            case QMessageBox::Save:
                                saveFileAs();
                                break;
            case QMessageBox::Cancel:
                                return;
        }
    }

    while (ui->data_table->rowCount() > 0)
    {
        ui->data_table->removeRow(0);
    }
    ui->customPlot->graph(0)->clearData();
    ui->customPlot->graph(1)->clearData();
    ui->customPlot->replot();
    ui->horizontalScrollBar->setEnabled(false);

}


void MainWindow::on_set_output_clicked() {
    if ( Device->isConnected() ) {
        if ( ui->set_output->text() == "Output ON" ) {
            ui->set_output->setText("Output OFF");
            ui->set_output->setChecked(true);
            Device->setOutput(true);
        } else {
            ui->set_output->setText("Output ON");
            ui->set_output->setChecked(false);
            Device->setOutput(false);
        }
    }
}

void MainWindow::on_doubleSpinBox_valueChanged(double arg1)
{
    if ( Device->isConnected() ) {
        BYTE value;
        int ret;
        arg1 = arg1 * 10;
        value = (float)( arg1 );
        ret = Device->setValue(1, value);

        if ( ret != 0 ) {
            ret = Device->setValue(1, value);
            if ( ret != 0 ) {
                //QMessageBox messageBox;
                //messageBox.setFixedSize(500,200);
                qDebug() << "error | valueChanged_voltage(): Value has not been changed";
                //messageBox.warning(0,"Warning","Value has not been changed");
            }
        }
    }
}

void MainWindow::on_doubleSpinBox_2_valueChanged(double arg1) {
    if ( Device->isConnected() ) {
        BYTE value;
        int ret;
        arg1 = arg1 * 100;
        value = (float)( arg1 );
        ret = Device->setValue(2, value);

        if ( ret != 0 ) {
            ret = Device->setValue(2, value);
            if ( ret != 0 ) {
                //QMessageBox messageBox;
                //messageBox.setFixedSize(500,200);
                qDebug() << "error | valueChanged_current(): Value has not been changed";
                //messageBox.warning(0,"Warning","Value has not been changed");
            }
        }
    }
}
