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

#include <QFontDatabase>
#include <QMessageBox>
#include <QMovie>
#include <QPaintEvent>
#include <QPainter>
#include <QTimer>
#include <Widgets/updatenotifywidget.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    isRecovery = false;
    setWindowFlag(Qt::FramelessWindowHint);
}

void MainWindow::initialize()
{
    createObjects();
    loadStaticData();
    bindConnection();

    updateWidget->initialize(this,versionContainer);
    entryWidget->initialize(this);
    versionSelectWidget->initialize(sendSystem,versionContainer);
    hashComparer->initialize(this,versionContainer);
    updateController->initialize(this,versionContainer);
    sendSystem->initialize(this,dataParser);
    dataParser->initialize(recognizeSystem);
    recognizeSystem->initialize(updateController,dataParser,this,hashComparer,client,versionContainer);
    resourceManager->painting();
    commonButtonGroupWidget->initialize(this,externalExecuter,sendSystem,client);
    commonButtonGroupWidget->show();

    setUpUi();


    emit sigCalculateHash();
    emit sigInitializeClient(this,recognizeSystem,externalExecuter,sendSystem,workerThread);

    screenChecker->check();

    emit sigSetConnect(dataParser->getServerSettings(),workerThread);

    checkAppAvailable();

    //post


}

void MainWindow::createObjects()
{
    updateWidget = new UpdateNotifyWidget;
    updateWidget->setParent(this);
    commonButtonGroupWidget = new CommonButtonGroupWidget;
    entryWidget = new EntryWidget;
    versionSelectWidget = new VersionSelectWidget;

    ui->changButtonGroup->addWidget(commonButtonGroupWidget);
    ui->interactiveGroup->addWidget(entryWidget);
    ui->interactiveGroup->addWidget(versionSelectWidget);

    workerThread = new QThread;
    animationThread = new QThread;

    client = new TCPClient;
    client->moveToThread(workerThread);

    dataParser = new DataParser;
    dataParser->moveToThread(workerThread);

    sendSystem = new SendSystem;
    sendSystem->moveToThread(workerThread);

    updateController = new UpdateController(dataParser,sendSystem);
    updateController->moveToThread(workerThread);

    recognizeSystem = new RecognizeSystem;
    recognizeSystem->moveToThread(workerThread);

    screenChecker = new ScreenChecker(this,dataParser,ui->displayLayout);
    externalExecuter = new ExternalExecuter;

    hashComparer = new HashComparer(dataParser);
    hashComparer->moveToThread(workerThread);

    versionContainer = new VersionContainer;
    resourceManager = new ResourceManager;

    workerThread->start();
    workerThread->setPriority(QThread::HighestPriority);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->setParent(this);

    movieLabel = new QLabel("MovieLabel");
    layout->addWidget(movieLabel);
    setLayout(layout);
    movieLabel->setStyleSheet("background-color:rgba(0,0,0,90)");

    timer = new QTimer;
}

void MainWindow::bindConnection()
{
    connect(timer,&QTimer::timeout,this,&MainWindow::slotDisableNotify);

    connect(this,&MainWindow::sigUpdateFilesOnServer,updateController,&UpdateController::updateFilesOnServer);
    connect(this,&MainWindow::sigInitializeClient,client,&TCPClient::initialize,Qt::AutoConnection);
    connect(this,&MainWindow::sigSetConnect,client,&TCPClient::setConnect,Qt::AutoConnection);
    connect(this,&MainWindow::sigSendCommand,client,&TCPClient::slotSendCommand,Qt::AutoConnection);
    connect(this,&MainWindow::sigSendXMLAnswer,sendSystem,&SendSystem::xmlAnswer,Qt::AutoConnection);

    connect(this,&MainWindow::sigGetConnected,client,&TCPClient::getIsConnected);
    connect(this,&MainWindow::sigCalculateHash,updateController,&UpdateController::calculateCommonHash);
    connect(this,&MainWindow::sigSendAutorization,sendSystem,&SendSystem::sendClientAutorization);
}

void MainWindow::updateProgress()
{
    filesLoaded++;
    float value = 100 / ((float)fileCountForUpdate / filesLoaded);
    commonButtonGroupWidget->updateProgressBar(value);
}

void MainWindow::loadComplete()
{
    externalExecuter->findApp();
    commonButtonGroupWidget->loadCompleteState();
    autoStart();
    ui->inlineTextDebug->setText(tr("Обновление завершено"));
    ui->offlineStartButton->setEnabled(true);
    ui->autostartCheckBox->hide();
    ui->offlineStartButton->show();

    dataParser->changeVersion(versionContainer->getServerVersionData()->getViewName());
    setTitle();
}

void MainWindow::setNeedUpdate(bool flag,quint64 size, quint64 fileCount,quint64 deleteCount)
{
    fileCountForUpdate = 0;
    filesLoaded = 0;
    fileCountForUpdate = fileCount;
    QString availableSizeText;

    if (flag && isRecovery)
    {
        ui->inlineTextDebug->setText(tr("Восстановление версии..."));

    }
    else if(flag)
    {
        QString result;
        if(fileCount > 0)
        {
            result = tr("Доступно обновление: ") + Tools::convertFileSize(size);
            result += tr("Количество файлов: ") + QString::number(fileCount);
        }
        else
        {
            result = tr("Файлов к удалению: ") + QString::number(deleteCount);
        }

        ui->inlineTextDebug->setText(result);
        commonButtonGroupWidget->needUpdateState(flag);
        ui->autostartCheckBox->show();
        activateLoadingAnimation(false);
    }
    else
    {
        ui->inlineTextDebug->setText(tr("Установлена последняя версия"));
        autoStart();
        commonButtonGroupWidget->lastVerInstalledState();
        ui->unsafeChangingButton->hide();
        ui->offlineStartButton->setEnabled(true);
        dataParser->changeVersion(versionContainer->getServerVersion());
        setTitle();
        activateLoadingAnimation(false);
    }
}

void MainWindow::showServerListWidget(QList<StreamingVersionData *> *serverData)
{
    entryWidget->hide();
    activateLoadingAnimation(false);
    versionSelectWidget->fillView(serverData);
    checkUpdate();
}

void MainWindow::lostConnection()
{
    commonButtonGroupWidget->updateProgressBar(0);
    slotConnectionState(false);
}

void MainWindow::serverBlocked()
{
    ui->notificationLabel->show();
    QPalette palette = ui->notificationLabel->palette();
    QColor orangeColor(255,165,0);
    palette.setColor(ui->notificationLabel->foregroundRole(),orangeColor);
    ui->notificationLabel->setText(tr("Сервер заблокирован"));

    ui->notificationLabel->setPalette(palette);
    timer->start(3000);
}

void MainWindow::checkLoginResult(ServerAuthorization *serverAuth)
{
    if (serverAuth->Result)
    {

        if (serverAuth->AccessType != "instructor") //временно для отладки загрузки на сервер
        {
            checkUpdate();
        }
        else
        {
            emit sigSendXMLAnswer(cmd_CheckVersionList);
        }

        dataParser->createAuthData(serverAuth);
        entryWidget->loginIsActive(false);
        ui->LanguageWidget->hide();
        ui->settingsButton->hide();
        ui->offlineStartButton->show();
        activateLoadingAnimation(true);
    }
    else
    {
        entryWidget->loginIsActive(true);
        ui->notificationLabel->setText(tr("Неверный логин/пароль"));
        timer->setInterval(3000);
        timer->start();

        QPalette palette = ui->notificationLabel->palette();
        palette.setColor(ui->notificationLabel->foregroundRole(), Qt::red);

        ui->notificationLabel->setPalette(palette);
        ui->notificationLabel->show();
    }

}

void MainWindow::checkAppAvailable()
{
    bool isAvailable = externalExecuter->findApp();
    commonButtonGroupWidget->startButtonActive(isAvailable);
    ui->offlineStartButton->setEnabled(isAvailable);
}

void MainWindow::checkLanguage(QString language)
{
    if (language == "RUS")
    {
        translator.load("QtLanguage_ru_RU",".");
    }
    else if(language == "ENG")
    {
        translator.load("QtLanguage_eng_EN",".");
    }

    qApp->installTranslator(&translator);
    ui->retranslateUi(this);
}

void MainWindow::autoStart()
{
    if(ui->autostartCheckBox->isChecked()){
        startUnityClient();
    }
}

void MainWindow::setTitle()
{
    ServerSettings *currentSettings = dataParser->getServerSettings();

    QString title = tr("Тренажер процедур технического обслуживания самолета RRJ-95NEW-100");
    title.append(" (" + currentSettings->LocalVersionName + ")");
    ui->headerLabel->setText(title);
}

void MainWindow::loadStaticData()
{
    ServerSettings *currentSettings = dataParser->getServerSettings();

    entryWidget->fillSettings(currentSettings);
    ui->languageComboBox->setCurrentText(currentSettings->Language);
    ui->autostartCheckBox->setChecked(currentSettings->isAutoStart);

    checkLanguage(currentSettings->Language);
    setTitle();
}

void MainWindow::showConnectionEmpty()
{
    QPalette palette = ui->notificationLabel->palette();
    palette.setColor(ui->notificationLabel->foregroundRole(),Qt::red);
    ui->notificationLabel->setText(tr("Соединение отсутсвует"));
    entryWidget->connectionEmptyState();
    updateWidget->hide();
    ui->offlineStartButton->show();
    ui->offlineStartButton->setGeometry(280,340,250,40);
    ui->settingsButton->show();
    ui->unsafeChangingButton->hide();
    versionSelectWidget->hide();
}

void MainWindow::disableUnsaveButton(bool flag)
{
    if(!flag) ui->unsafeChangingButton->show();
    else ui->unsafeChangingButton->hide();
}

void MainWindow::slotConnectionState(bool flag)
{
    ui->notificationLabel->show();
    QPalette palette = ui->notificationLabel->palette();

    activateLoadingAnimation(false);

    if(flag)
    {
        palette.setColor(ui->notificationLabel->foregroundRole(),Qt::green);
        ui->notificationLabel->setText(tr("Соединение установлено"));
        entryWidget->loginIsActive(true);

        ui->offlineStartButton->show();
        ui->offlineStartButton->setGeometry(540,549,250,40);
    }
    else
    {
        showConnectionEmpty();
    }

    ui->notificationLabel->setPalette(palette);
    timer->start(3000);
}

void MainWindow::slotServerDisconnect()
{
    commonButtonGroupWidget->disconnectState();
    ui->autostartCheckBox->hide();
    ui->inlineTextDebug->setText("");
    slotConnectionState(false);
}

void MainWindow::slotDisableNotify()
{
    ui->notificationLabel->hide();

    QPalette palette = ui->notificationLabel->palette();
    palette.setColor(ui->notificationLabel->foregroundRole(), Qt::black);

    ui->notificationLabel->setPalette(palette);
    timer->stop();
}

void MainWindow::callUpdateList()
{
    hashComparer->setWidget(updateWidget);
    emit sigSendXMLAnswer(cmd_GetServerHash);
}


void MainWindow::login()
{
    if (!client->getIsConnected())
    {
        showConnectionEmpty();
        return;
    }

    entryWidget->loginIsActive(false);
    ClientAutorization *autorization = entryWidget->getAuthData();
    dataParser->createAuthMessage(autorization);
    emit sigSendAutorization();

}

void MainWindow::saveServerSettingsWithConnect()
{
    activateLoadingAnimation(true);
    entryWidget->settingsWidgetIsActive(false);

    if(client->getIsConnected())
    {
        entryWidget->loginIsActive(true);
        ui->offlineStartButton->show();
        activateLoadingAnimation(false);
        return;
    }
    //TODO: не заполняется 2 поля (автостарт и язык)
    ServerSettings *settings = entryWidget->getServerSettings();
    settings->LocalVersionName = dataParser->getServerSettings()->LocalVersionName;
    dataParser->createServerSettings(settings);

    emit sigSetConnect(settings,workerThread);
}

void MainWindow::on_settingsButton_clicked()
{
    entryWidget->settingsState();
    ui->offlineStartButton->hide();
}

void MainWindow::on_languageComboBox_activated(const QString &arg1)
{
    qDebug() << arg1;
    dataParser->saveClientSettrings(arg1,ui->autostartCheckBox->isChecked());
    checkLanguage(arg1);
    ui->retranslateUi(this);
}

void MainWindow::loadToServer()
{
    ui->inlineTextDebug->setText(tr("Отправка файлов..."));
    commonButtonGroupWidget->showProgressBar(true);
    ui->offlineStartButton->setEnabled(false);
    updateWidget->hide();
    ui->unsafeChangingButton->hide();
    emit sigUpdateFilesOnServer(hashComparer->getFilesForUpdate());
}

void MainWindow::undoCurrentChanges()
{
    isRecovery = true;
    emit sigSendCommand("check");

    commonButtonGroupWidget->showProgressBar(true);
    ui->offlineStartButton->setEnabled(false);
    updateWidget->hide();

    activateLoadingAnimation(true);

    //delay

    QTime dieTime= QTime::currentTime().addSecs(10);
    while (QTime::currentTime() < dieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

     activateLoadingAnimation(true);

    emit sigSendCommand("update");
    commonButtonGroupWidget->startUpdateState();

    isRecovery = false;
     activateLoadingAnimation(false);
}

void MainWindow::on_offlineStartButton_clicked()
{
    QString username = "offlineUser";
    QString password = "000000";

    dataParser->createAuthDataOffline(username,password);
    startUnityClient();
}


void MainWindow::on_unsafeChangingButton_clicked()
{
    updateWidget->show();
}

void MainWindow::on_exitButton_clicked()
{
    exit(0);
}

void MainWindow::checkUpdate()
{
    emit sigSendCommand("check");
    ui->inlineTextDebug->setText(tr("Проверка обновлений..."));
}

void MainWindow::showUpdateInfo()
{
    activateLoadingAnimation(false);
    updateWidget->showWithFill();
    ui->unsafeChangingButton->show();
    entryWidget->hide();
    commonButtonGroupWidget->show();
    ui->offlineStartButton->setGeometry(540,549,250,40);
    fileCountForUpdate = hashComparer->getFileUpdateCount();

    filesLoaded = 0;
}

void MainWindow::showCompleteDialogBox()
{
    ui->inlineTextDebug->setText(tr("Загрузка завершена"));
    activateLoadingAnimation(true);

    QTime dieTime= QTime::currentTime().addSecs(10);        //DELAY ДЛЯ ПЕРЕСЧЕТА ХЭША НА СЕРВЕРЕ
    while (QTime::currentTime() < dieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

    activateLoadingAnimation(false);
    checkUpdate();
}

void MainWindow::startUnityClient()
{
    externalExecuter->callApp();
    emit sigSendXMLAnswer("DISABLE");
}

void MainWindow::setCurrentVersionName(StreamingVersionData *version)
{
    versionContainer->setLocalVersionData(version);
}

void MainWindow::setUpUi()
{
    ui->notificationLabel->hide();
    ui->unsafeChangingButton->hide();

    ui->offlineStartButton->show();
    ui->offlineStartButton->setEnabled(false);
    ui->offlineStartButton->setGeometry(540,549,250,40);

    ui->settingsButton->setIcon(*resourceManager->getSettingsIcon());

    QSize cautionIconSize(30,30);
    ui->unsafeChangingButton->setIcon(*resourceManager->getUnsavedIcon());
    ui->unsafeChangingButton->setIconSize(cautionIconSize);

    movieLabel->setGeometry(367,300,70,70);
    movieLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
    movieLabel->setMovie(resourceManager->getMovie());

    QSize iconSize(30,30);
    ui->exitButton->setIcon(*resourceManager->getCloseIcon());
    ui->exitButton->setIconSize(iconSize);

    ui->displayGroupWidget->show();
    ui->autostartCheckBox->hide();

    activateLoadingAnimation(true);
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
    {
        if (entryWidget->isLoginFieldsFill()) return;
        login();
    }
}

void MainWindow::activateLoadingAnimation(bool flag)
{
    if (flag)
    {
        movieLabel->show();
        resourceManager->startLoadingAnim();
    }
    else
    {
        movieLabel->hide();
        resourceManager->stopLoadingMovie();
    }
}

MainWindow::~MainWindow()
{
    workerThread->quit();
    workerThread->wait();

    emit sigSendXMLAnswer(cmd_Disable);

    delete workerThread;
    delete ui;
}






