#include "statuswidget.h"
#include "ui_statuswidget.h"
#include "widgets/mainwindow.h"
#include "models/patchdownloader.h"
#include "models/lotrodatmanager.h"
#include "constants.h"

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

StatusWidget::StatusWidget(QSettings* settings, PatchDownloader* patch_downloader, LotroDatManager* lotro_dat_manager, QWidget *parent) :
    QWidget(parent), app_settings(settings), patch_updater(patch_downloader), lotro_manager(lotro_dat_manager),
    ui(new Ui::StatusWidget)
{

    ui->setupUi(this);
    ui->server_status_widget->setupUpdater(settings->value("Network/game_servers_status", "http://translate.lotros.ru/servers.txt").toUrl(),
                                           settings->value("Network/game_servers_message", "http://translate.lotros.ru/profmessage.txt").toUrl());
    last_progress_update_time.start();

    connect(patch_updater, &PatchDownloader::checkForUpdatesStarted, this, &StatusWidget::onPatchDownloaderStarted, Qt::QueuedConnection);
    connect(patch_updater, &PatchDownloader::progressChanged, this, &StatusWidget::onPatchDownloaderProgressChanged, Qt::QueuedConnection);
    connect(patch_updater, &PatchDownloader::checkForUpdatesFinished, this, &StatusWidget::onPatchDownloaderFinished, Qt::QueuedConnection);
    connect(patch_updater, &PatchDownloader::changePatchStatus, this, &StatusWidget::updatePatchStatus);

    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showCompletedTooltip, this, &StatusWidget::setToolTipToWeeklyCodeComplete);
    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showHelpTooltip, this, &StatusWidget::setToolTipToWeeklyCodeHelp);
    connect(ui->weekly_code_widget, &WeeklyCodeWidget::showNoTooltip, this, &StatusWidget::resetToolTip);

    connect(ui->news_list, &NewsListWidget::showHelpToolTip, this, &StatusWidget::setToolTipToNewsHelp);
    connect(ui->news_list, &NewsListWidget::showNoToolTip, this, &StatusWidget::resetToolTip);

    connect(ui->server_status_widget, &ServerStatusWidget::updateServersTooltip, ui->server_status_tooltip, &QLabel::setText);
    connect(ui->server_status_widget, &ServerStatusWidget::showServersTooltip, this, &StatusWidget::setToolTipToServersStatus);
    connect(ui->server_status_widget, &ServerStatusWidget::showNoTooltip, this, &StatusWidget::resetToolTip);

    tooltip_effects[ui->news_tooltip->objectName()] = new QGraphicsOpacityEffect(ui->news_tooltip);
    tooltip_effects[ui->weekly_code_tooltip_1->objectName()] = new QGraphicsOpacityEffect(ui->weekly_code_tooltip_1);
    tooltip_effects[ui->weekly_code_tooltip_2->objectName()] = new QGraphicsOpacityEffect(ui->weekly_code_tooltip_2);
    tooltip_effects[ui->patches_status->objectName()] = new QGraphicsOpacityEffect(ui->patches_status);
    tooltip_effects[ui->server_status_tooltip->objectName()] = new QGraphicsOpacityEffect(ui->server_status_tooltip);

    tooltip_animations[ui->news_tooltip->objectName()] = new QPropertyAnimation(tooltip_effects[ui->news_tooltip->objectName()], "opacity");
    tooltip_animations[ui->weekly_code_tooltip_1->objectName()] = new QPropertyAnimation(tooltip_effects[ui->weekly_code_tooltip_1->objectName()], "opacity");
    tooltip_animations[ui->weekly_code_tooltip_2->objectName()] = new QPropertyAnimation(tooltip_effects[ui->weekly_code_tooltip_2->objectName()], "opacity");
    tooltip_animations[ui->patches_status->objectName()] = new QPropertyAnimation(tooltip_effects[ui->patches_status->objectName()], "opacity");
    tooltip_animations[ui->server_status_tooltip->objectName()] = new QPropertyAnimation(tooltip_effects[ui->server_status_tooltip->objectName()], "opacity");

    ui->news_tooltip->setGraphicsEffect(tooltip_effects[ui->news_tooltip->objectName()]);
    ui->weekly_code_tooltip_1->setGraphicsEffect(tooltip_effects[ui->weekly_code_tooltip_1->objectName()]);
    ui->weekly_code_tooltip_2->setGraphicsEffect(tooltip_effects[ui->weekly_code_tooltip_2->objectName()]);
    ui->patches_status->setGraphicsEffect(tooltip_effects[ui->patches_status->objectName()]);
    ui->server_status_tooltip->setGraphicsEffect(tooltip_effects[ui->server_status_tooltip->objectName()]);

    foreach (QPropertyAnimation* animation, tooltip_animations) {
        animation->setDuration(350);
        animation->setStartValue(0);
        animation->setEndValue(1);
        animation->setDirection(QAbstractAnimation::Forward);
    }

    foreach (QGraphicsOpacityEffect* effect, tooltip_effects) {
        effect->setOpacity(0);
    }

    active_tooltip = nullptr;
    resetToolTip();
}

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

void StatusWidget::updateFontsSizes()
{
    QFont pt10_font = QFont(ui->news_label->font());
    pt10_font.setPixelSize(pixels_in_10_pt);
    QFont pt9_font = QFont(ui->progress_label->font());
    pt9_font.setPixelSize(pixels_in_9_pt);
    QFont pt11_font = QFont(ui->game_button->font());
    pt11_font.setPixelSize(pixels_in_11_pt);
    QFont pt8_font = QFont(ui->images_label->font());
    pt8_font.setPixelSize(pixels_in_8_pt);

    ui->progress_label->setFont(crimson_10pt);
    ui->game_button->setFont(trajan_11pt);
    ui->news_label->setFont(trajan_10pt);

    ui->images_label->setFont(crimson_11pt);
    ui->images_status->setFont(crimson_11pt);
    ui->sounds_label->setFont(crimson_11pt);
    ui->sounds_status->setFont(crimson_11pt);
    ui->texts_label->setFont(crimson_11pt);
    ui->texts_status->setFont(crimson_11pt);
    ui->videos_label->setFont(crimson_11pt);
    ui->videos_status->setFont(crimson_11pt);

    ui->news_tooltip->setFont(garamond_11pt);
    ui->weekly_code_tooltip_1->setFont(garamond_11pt);
    ui->weekly_code_tooltip_2->setFont(garamond_11pt);
    ui->server_status_tooltip->setFont(garamond_11pt);
}

void StatusWidget::resizeEvent(QResizeEvent *event)
{
    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(365, 114) * coefficient);

    updateFontsSizes();
}

void StatusWidget::onPatchDownloaderStarted()
{
    qDebug() << "Status widget received DownloadStarted signal!";
    ui->game_button->setDisabled(true);
    ui->progress_label->setText("Проверка обновлений...");
    ui->progressBar->setValue(0);
}

void StatusWidget::onPatchDownloaderFinished()
{
    ui->progress_label->setText("Все патчи загружены!");
    ui->progressBar->setValue(100);
    ui->game_button->setDisabled(false);
}

void StatusWidget::onPatchDownloaderProgressChanged(QList<PatchDownloadData> patches_data)
{
    if (last_progress_update_time.elapsed() < 200) {
        return;
    } else {
        last_progress_update_time.restart();
    }

    foreach (PatchDownloadData data, patches_data) {
        if (data.patch_name == "general") {
            ui->progress_label->setText("Скачивание переводов " + data.download_speed_formatted + ".\nЗагружено "
                                       + Downloader::getSizeFormatted(data.bytesDownloaded) + " из " + Downloader::getSizeFormatted(data.bytesTotal)
                                       + " (" + QString::number(double(data.bytesDownloaded) * 100.0 / double(data.bytesTotal), 'f', 1) + "%) "
                                       + "\nОставшееся время: " + data.elapsed_time_formatted);
            ui->progressBar->setValue(data.bytesDownloaded * 100 / data.bytesTotal);
        } else {
            updatePatchStatus(data.patch_name, "Скачивание " + QString::number(double(data.bytesDownloaded) * 100.0 / double(data.bytesTotal), 'f', 1) + "% (" + data.download_speed_formatted + ")");
        }
    }
}

void StatusWidget::updatePatchStatus(QString patch_name, QString status)
{
    QString status_label_name = patch_name + "s_status";
    QLabel* status_label = findChild<QLabel*>(status_label_name);
    if (!status_label)
        return;

    status_label->setText(status);
}

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

void StatusWidget::setToolTipToWeeklyCodeHelp()
{
    fadeBetweenToolTips(ui->weekly_code_tooltip_1);
}

void StatusWidget::setToolTipToWeeklyCodeComplete()
{
    fadeBetweenToolTips(ui->weekly_code_tooltip_2);
}

void StatusWidget::setToolTipToNewsHelp()
{
    fadeBetweenToolTips(ui->news_tooltip);
}

void StatusWidget::setToolTipToServersStatus()
{
    fadeBetweenToolTips(ui->server_status_tooltip);
}

void StatusWidget::resetToolTip()
{
    fadeBetweenToolTips(ui->patches_status);
}

void StatusWidget::fadeBetweenToolTips(QWidget* next_tooltip)
{
    if (active_tooltip) {
        QPropertyAnimation* active_tooltip_anim = tooltip_animations[active_tooltip->objectName()];

        active_tooltip_anim->setDirection(QAbstractAnimation::Backward);

        if (active_tooltip_anim->state() == QAbstractAnimation::Stopped)
            active_tooltip_anim->start();
    }

    QPropertyAnimation* next_active_tooltip_anim = tooltip_animations[next_tooltip->objectName()];
    next_active_tooltip_anim->setDirection(QAbstractAnimation::Forward);

    if (next_active_tooltip_anim->state() == QAbstractAnimation::Stopped)
        next_active_tooltip_anim->start();


    active_tooltip = next_tooltip;
}
