#include "ui_statuswidget.h"
#include "statuswidget.h"

#include "models/patchlist.h"

#include "widgets/mainwindow.h"

#include "constants.h"

#include <QDesktopServices>
#include <QUrl>
#include <QDebug>
#include <QMessageBox>
#include <QRandomGenerator>

StatusWidget::StatusWidget(PatchList *legacy_patches, QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::StatusWidget)
    , legacy_patches_(legacy_patches)
{
    ui->setupUi(this);
    last_statusbar_update_time_.start();
    ui->galadriel_tooltip_example->hide();

    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showCompletedTooltip, this, [this](){setToolTipMessage("ЕЖЕНЕДЕЛЬНЫЙ КОД СКОПИРОВАН В БУФЕР ОБМЕНА", E_INFO);});
    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showHelpTooltip, this, [this](){setToolTipMessage("КЛИКНИТЕ ПО ЕЖЕНЕДЕЛЬНОМУ КОДУ, ЧТОБЫ СКОПИРОВАТЬ ЕГО", E_INFO);});
    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);});

    connect(ui->news_list, &NewsListWidget::showHelpToolTip, this, [this](){setToolTipMessage("НАЖМИТЕ НА ЗАГОЛОВОК НОВОСТИ, ЧТОБЫ ОТКРЫТЬ ЕЕ В БРАУЗЕРЕ", E_INFO);});
    connect(ui->news_list, &NewsListWidget::showNoToolTip, this, [this](){unsetToolTipMessage(E_INFO);});

    connect(ui->server_status_widget, &ServerStatusWidget::showServersTooltip, this, [this](QString message){setToolTipMessage(message, E_INFO);});
    connect(ui->server_status_widget, &ServerStatusWidget::showNoTooltip, this, [this](){unsetToolTipMessage(E_INFO);});

    connect(legacy_patches_, &PatchList::patchOperationsStarted, this, &StatusWidget::onPatchTotalOperationsStarted);
    connect(legacy_patches_, &PatchList::patchOperationsFinished, this, &StatusWidget::onPatchTotalOperationsFinished);
    connect(legacy_patches_, &PatchList::progressChanged, this, &StatusWidget::updatePatchProgressStatus);

    generateRandomTooltipMessage();
    random_tooltip_generator_timer_.setInterval(5 * 1000);
    connect(&random_tooltip_generator_timer_, &QTimer::timeout, this, &StatusWidget::generateRandomTooltipMessage);
    random_tooltip_generator_timer_.start();

    process_completed_tooltip_hide_timer_.setInterval(10 * 1000); // 10 seconds message "Installation completed" will be shown
    connect(&process_completed_tooltip_hide_timer_, &QTimer::timeout, this, [this](){unsetToolTipMessage(E_PROCESS);});
}

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

void StatusWidget::updateFontsSizes()
{
    ui->game_button->setFont(trajan_11pt);
    ui->news_label->setFont(trajan_10pt);
}

void StatusWidget::setToolTipMessage(QString message, StatusWidget::ToolTipState state)
{
    tooltip_messages_[state] = message;
    tooltip_state_ = ToolTipState(int(tooltip_state_) | int(state));

    QString message_id = message;
    if (state == E_PROCESS) {
        message_id = "E_PROCESS";
    }

    if (!tooltip_widgets_.contains(message_id)) {
        createTooltipMessageWidget(message_id);
    }
    tooltip_widgets_[message_id]->setText(message);

    if (tooltip_state_ < state * 2) {
        fadeBetweenToolTips(message_id);
    }
}

void StatusWidget::unsetToolTipMessage(StatusWidget::ToolTipState state)
{
    tooltip_state_ = ToolTipState(int(tooltip_state_) & (~int(state)));

    ToolTipState showing_state = E_RANDOM;

    if (tooltip_state_ & E_INFO) {
        showing_state = E_INFO;
    } else if (tooltip_state_ & E_ERROR) {
        showing_state = E_ERROR;
    } else if (tooltip_state_ & E_PROCESS) {
        showing_state = E_PROCESS;
    }

    QString message_id = tooltip_messages_[showing_state];
    if (showing_state == E_PROCESS) {
        message_id = "E_PROCESS";
    }

    if (!tooltip_widgets_.contains(message_id)) {
        createTooltipMessageWidget(message_id);
    }
    tooltip_widgets_[message_id]->setText(tooltip_messages_[showing_state]);
    fadeBetweenToolTips(message_id);
}

void StatusWidget::resizeEvent(QResizeEvent *)
{
    double coefficient = window_width / default_window_width;
//    ui->game_button->move(QPoint(820, 460) * coefficient);
//    ui->game_button->resize(QSize(150, 60) * coefficient);
//    ui->progressBar->move(QPoint(320, 480) * coefficient);
//    ui->progressBar->resize(QSize(470, 40) * coefficient);
//    ui->progress_label->move(QPoint(330, 390) * coefficient);
//    ui->progress_label->resize(QSize(380, 90) * coefficient);
//    ui->news_label->move(QPoint(45, 33)* coefficient);
//    ui->news_label->resize(QSize(180, 21) * coefficient);
//    ui->news_scroll_area->move(QPoint(40, 75) * coefficient);
//    ui->news_scroll_area->resize(QSize(240, 440) * coefficient);
//    ui->server_status_widget->move(QPoint(820, 90) * coefficient);
//    ui->server_status_widget->resize(QSize(155, 320) * coefficient);
//    ui->weekly_code_widget->move(QPoint(810, 13) * coefficient);
//    ui->weekly_code_widget->resize(QSize(173, 57) * coefficient);
//    ui->galadriel_widget->move(QPoint(320, 20) * coefficient);
//    ui->galadriel_widget->resize(QSize(531, 461) * coefficient);

//    ui->news_tooltip->move(QPoint(38, 13) * coefficient);
//    ui->news_tooltip->resize(QSize(365, 114) * coefficient);
//    ui->weekly_code_tooltip_1->move(QPoint(38, 13) * coefficient);
//    ui->weekly_code_tooltip_1->resize(QSize(365, 114) * coefficient);
//    ui->weekly_code_tooltip_2->move(QPoint(38, 13) * coefficient);
//    ui->weekly_code_tooltip_2->resize(QSize(365, 114) * coefficient);
//    ui->server_status_tooltip->move(QPoint(38, 13) * coefficient);
//    ui->server_status_tooltip->resize(QSize(365, 114) * coefficient);

//    ui->patches_status->move(QPoint(38, 13) * coefficient);
//    ui->patches_status->resize(QSize(385, 114) * coefficient);

    updateFontsSizes();
}

void StatusWidget::generateRandomTooltipMessage()
{
    quint32 number = QRandomGenerator::system()->generate();
    setToolTipMessage("СЛУЧАЙНОЕ СООБЩЕНИЕ №" + QString::number(number), E_RANDOM);
}

void StatusWidget::fadeBetweenToolTips(QString tooltip_id)
{
    if (tooltip_id == current_tooltip_message_) {
        return;
    }

    QPropertyAnimation* showing_anim = tooltip_animations_[tooltip_id];
    showing_anim->setDirection(QAbstractAnimation::Forward);
    if (showing_anim->state() == QAbstractAnimation::Stopped) {
        showing_anim->start();
    }

    if (tooltip_widgets_.contains(current_tooltip_message_)) {
        QString msg = current_tooltip_message_;
        connect(tooltip_animations_[current_tooltip_message_], &QPropertyAnimation::finished, this, [&, msg](){
            if (tooltip_effects_.contains(msg) && tooltip_effects_[msg]->opacity() == 0) {
                tooltip_widgets_.take(msg)->deleteLater();
                tooltip_effects_.take(msg)->deleteLater();
                tooltip_animations_.take(msg)->deleteLater();
            }
        });

        QPropertyAnimation* hiding_anim = tooltip_animations_[current_tooltip_message_];
        hiding_anim->setDirection(QAbstractAnimation::Backward);
        if (hiding_anim->state() == QAbstractAnimation::Stopped) {
            hiding_anim->start();
        }
    }

    current_tooltip_message_ = tooltip_id;
}

void StatusWidget::onPatchTotalOperationsStarted()
{
    all_patch_operations_finished_ = false;
    ui->game_button->setEnabled(false);
    ui->check_for_updates_button->setEnabled(false);
    setToolTipMessage("Запуск процесса проверки и установки русификации...", E_PROCESS);
}

void StatusWidget::onPatchTotalOperationsFinished()
{
    all_patch_operations_finished_ = true;
    ui->game_button->setEnabled(true);
    ui->check_for_updates_button->setEnabled(true);
    setToolTipMessage("Все процессы установки русификации завершены. Можно играть. Mae govannen. Еще какой-то текст...", E_PROCESS);
    process_completed_tooltip_hide_timer_.start();
}

void StatusWidget::on_game_button_clicked()
{
    MainWindow* window = qobject_cast<MainWindow*>(parentWidget()->parentWidget()->parentWidget());
    window->showChooseVersionDialog();
}

void StatusWidget::updatePatchProgressStatus(Patch::OperationProgress progress)
{
    if (last_statusbar_update_time_.elapsed() > 400) {
        QString text = "Выполнение операций...";
        if (progress.download_total_bytes != 0) {
            text += "\nЗагрузка данных: " + QString::number(progress.getDownloadPercent(), 'f', 1) + "% ("
                    + Downloader::getSizeFormatted(progress.download_finished_bytes) + "/"
                    + Downloader::getSizeFormatted(progress.download_total_bytes) + ", "
                    + Downloader::getSpeedFormatted(progress.download_speed) + ")\n"
                    + "До конца загрузки: " + Downloader::getElapsedTimeFormatted(progress.download_elapsed_time);
        }

        if (progress.install_total_parts != 0) {
            text += "\nПрименение патчей: " + QString::number(progress.getInstallPercent()) + "% "
                    + "(часть " + QString::number(progress.install_finished_parts + 1) + " из " + QString::number(progress.install_total_parts);
        }

        setToolTipMessage(text, E_PROCESS);
        last_statusbar_update_time_.restart();
    }
}

void StatusWidget::createTooltipMessageWidget(QString tooltip_id)
{
    tooltip_widgets_[tooltip_id] = new QLabel(ui->galadriel_widget);
    tooltip_widgets_[tooltip_id]->setGeometry(ui->galadriel_tooltip_example->geometry());
    tooltip_widgets_[tooltip_id]->setStyleSheet(ui->galadriel_tooltip_example->styleSheet());
    tooltip_widgets_[tooltip_id]->setFont(ui->galadriel_tooltip_example->font());
    tooltip_widgets_[tooltip_id]->setWordWrap(true);
    tooltip_widgets_[tooltip_id]->setAlignment(Qt::AlignCenter);
    tooltip_widgets_[tooltip_id]->show();

    tooltip_effects_[tooltip_id] = new QGraphicsOpacityEffect(tooltip_widgets_[tooltip_id]);
    tooltip_effects_[tooltip_id]->setOpacity(0);

    tooltip_animations_[tooltip_id] = new QPropertyAnimation(tooltip_effects_[tooltip_id], "opacity");
    tooltip_animations_[tooltip_id]->setDuration(300);
    tooltip_animations_[tooltip_id]->setStartValue(0);
    tooltip_animations_[tooltip_id]->setEndValue(1);
    tooltip_animations_[tooltip_id]->setDirection(QAbstractAnimation::Forward);

    tooltip_widgets_[tooltip_id]->setGraphicsEffect(tooltip_effects_[tooltip_id]);
}

void StatusWidget::on_check_for_updates_button_clicked()
{
    QMetaObject::invokeMethod(legacy_patches_, &PatchList::update, Qt::QueuedConnection);
}
