#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include "utils.h"
#include "progress_event.h"

#include <QDateTime>
#include <QMessageBox>
#include <QDebug>
#include <QScrollBar>

MainWindow::MainWindow(Worker *worker, QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_worker(worker)
    , m_width(70)
    , m_progressRunning(false)
    , m_progressValue(0) {
    ui->setupUi(this);

    ui->updateProgress->setRange(0, 100);
    ui->updateProgress->reset();

    QStringList lst;
    QString start = QDateTime::currentDateTime().toString(Qt::ISODate);
    lst << QString("Start: ") + start.leftJustified(m_width-10);
    lst << QString("").leftJustified(m_width-3, '=');
    lst << QString("Machine number  : %1 ").arg(m_worker->machineNr()).leftJustified(m_width-3);
    lst << QString("Customer number : %1 ").arg(m_worker->customerNr()).leftJustified(m_width-3);
    lst << QString("Zone number     : %1 (%2)").arg(m_worker->zoneNr()).arg(Utils::zoneName(m_worker->zoneNr())).leftJustified(m_width-3);
    lst << QString("").leftJustified(m_width-3, '=');

    ui->updateStatus->setText(lst.join('\n'));
    ui->updateStatus->setEnabled(true);

    m_startTimer = new QTimer(this);
    connect(m_startTimer, SIGNAL(timeout()), m_worker, SLOT(update()));
    m_startTimer->setSingleShot(true);
    m_startTimer->start(1000);

    m_exitTimer = new QTimer(this);
    connect(m_exitTimer, SIGNAL(timeout()), ui->exit, SLOT(click()));
    m_exitTimer->setSingleShot(true);
    m_exitTimer->start(1800 * 1000);

    connect(ui->exit, SIGNAL(clicked()), this, SLOT(onQuit()));
    connect(m_worker, SIGNAL(disableExit()), this, SLOT(onDisableExit()));
    connect(m_worker, SIGNAL(enableExit()), this, SLOT(onEnableExit()));
    connect(m_worker, SIGNAL(stopStartTimer()), this, SLOT(onStopStartTimer()));
    connect(m_worker, SIGNAL(restartExitTimer()), this, SLOT(onRestartExitTimer()));
    connect(m_worker, SIGNAL(appendText(QString, QString)), this, SLOT(onAppendText(QString, QString)));
    connect(m_worker, SIGNAL(showErrorMessage(QString,QString)), this, SLOT(onShowErrorMessage(QString,QString)));
    connect(m_worker, SIGNAL(replaceLast(QString, QString)), this, SLOT(onReplaceLast(QString,QString)));

    ui->updateStatus->setText(lst.join('\n'));
    ui->updateStatus->setEnabled(true);
}

MainWindow::~MainWindow() {
    delete m_startTimer;
    delete m_exitTimer;
    delete ui;
}

void MainWindow::customEvent(QEvent *event) {
    if (event->type() == ProgressEvent::type()) {
        ProgressEvent *pevent = (ProgressEvent *)event;
        int const progress = pevent->progressPercent();
        QObject const *sender = pevent->sender();
        if (sender == this) {
            switch(progress) {
            case 0: {
                ui->updateProgress->reset();
            } break;
            case START_PROGRESS_LOOP: {
                m_progressRunning = true;
                ui->updateProgress->reset();
                m_progressValue = 10;
                QApplication::postEvent(this, new ProgressEvent(this, m_progressValue));
            } break;
            case STOP_PROGRESS_LOOP: {
                m_progressRunning = false;
                m_progressValue -= 10;
                m_worker->setProgress(m_progressValue/10);
            } break;
            default: {
                    if (m_progressRunning) {
                        m_progressValue = progress;
                        ui->updateProgress->setValue(progress/10);
                        QApplication::postEvent(this, new ProgressEvent(this, progress+10));
                        QThread::msleep(500);
                    }
                }
            }
        } else
        if (sender == m_worker) {
            switch(progress) {
            case 0: {
                ui->updateProgress->reset();
            } break;
            case START_PROGRESS_LOOP: {
                QApplication::postEvent(this, new ProgressEvent(this, START_PROGRESS_LOOP));
            } break;
            case STOP_PROGRESS_LOOP: {
                QApplication::postEvent(this, new ProgressEvent(this, STOP_PROGRESS_LOOP));
            } break;
            default:{
                ui->updateProgress->setValue(progress);
            }}
        } else {
            qCritical() << "!!! UNKNOWN SENDER !!!";
        }
    }

    QThread::yieldCurrentThread();
}

void MainWindow::onStopStartTimer() {
    m_startTimer->stop();
}

void MainWindow::onDisableExit() {
   ui->exit->setEnabled(false);
}

void MainWindow::onEnableExit() {
   ui->exit->setEnabled(true);
}

void MainWindow::onRestartExitTimer() {
    m_exitTimer->stop();
    m_exitTimer->start(60 * 1000);
}

void MainWindow::onQuit() {
    m_exitTimer->stop();
    qCritical() << QString("ON QUIT: EXIT CODE %1").arg(m_worker->returnCode());
    qApp->exit(m_worker->returnCode());
}

void MainWindow::scrollDownTextEdit() {
    ui->updateStatus->setEnabled(true);

    QTextCursor tmpCursor = ui->updateStatus->textCursor();
    tmpCursor.movePosition(QTextCursor::End);
    ui->updateStatus->setTextCursor(tmpCursor);
    ui->updateStatus->ensureCursorVisible();
}

void MainWindow::onAppendText(QString text, QString suffix) {
    QString editText = ui->updateStatus->toPlainText();
    if (!suffix.isNull() && suffix.size() > 0) {
        //qInfo() << "TEXT" << text << "SUFFIX" << suffix;
        if (suffix == Worker::UPDATE_STEP_SUCCESS || suffix == Worker::UPDATE_STEP_FAIL) {
            editText += QString("\n").leftJustified(m_width-3, '=');
            editText += " ";
        }
        editText += (QString("\n") + text).leftJustified(m_width - (2 + suffix.size()) ) + suffix;
    } else {
        editText += text.leftJustified(m_width-9);
    }

    Utils::printLineEditInfo(editText.split('\n'));

    ui->updateStatus->setPlainText(editText.trimmed());
    ui->updateStatus->setEnabled(true);
}

void MainWindow::onReplaceLast(QString text, QString suffix) {
        //qInfo() << "REPL TEXT" << text << "SUFFIX" << suffix;
    QString editText = ui->updateStatus->toPlainText();
    QStringList lines = editText.split('\n');
    if (lines.size() > 0) {
        lines.removeLast();
        if (!suffix.isNull() && suffix.size() > 0 && suffix != "\n") {
            lines += text.leftJustified(m_width-10) + suffix;
        } else {
            lines += text.leftJustified(m_width-10);
        }
    }

    Utils::printLineEditInfo(lines);

    ui->updateStatus->setText(lines.join('\n').trimmed());
    ui->updateStatus->setEnabled(true);
}

void MainWindow::onShowErrorMessage(QString title, QString text) {
    text = text.leftJustified(50, ' ');
    QMessageBox msgBox(QMessageBox::NoIcon, title,
                       text, QMessageBox::Ok,
                       nullptr, Qt::FramelessWindowHint);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.defaultButton()->setVisible(false);

    QTimer *t = new QTimer(this);
    connect(t, SIGNAL(timeout()), msgBox.defaultButton(), SLOT(click()));
    t->setSingleShot(true);
    t->start(5 * 1000);

    if(msgBox.exec() == QMessageBox::Ok) {
      // do something
    } else {
      // do something else
    }
}
