/***********************************************************************
 *                                                                     *
 * Copyright 2016  Lorenzo Porta (Vindex17) <vindex17@outlook.it>      *
 *                                                                     *
 * This program is free software; you can redistribute it and/or       *
 * modify it under the terms of the GNU General Public License as      *
 * published by the Free Software Foundation; either version 3 of      *
 * the License or any later version accepted by the membership of      *
 * KDE e.V. (or its successor approved by the membership of KDE        *
 * e.V.), which shall act as a proxy defined in Section 14 of          *
 * version 3 of the license.                                           *
 *                                                                     *
 * This program is distributed in the hope that it will be useful,     *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
 * GNU General Public License for more details.                        *
 *                                                                     *
 * You should have received a copy of the GNU General Public License   *
 * along with this program. If not, see <http://www.gnu.org/licenses/> *
 *                                                                     *
 ***********************************************************************/


#pragma once


#include <KIO/Job>
#include <KSqueezedTextLabel>
#include <QDialog>
#include <QPointer>
#include <QProgressBar>


typedef std::result_of<decltype(&QProgressBar::value)(QProgressBar)>::type progress_bar_value_t;

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

struct ProgressDialog : public QDialog
{
    explicit ProgressDialog(QWidget * const, const QString &);
    Q_DISABLE_COPY(ProgressDialog)

    void reset(const progress_bar_value_t &);
    void update() __attribute__((always_inline));

private:
    QProgressBar progress_bar;
};

inline void ProgressDialog::update() {progress_bar.setValue(progress_bar.value()+1);}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

struct TaskProgressDialog : public QDialog
{
    explicit TaskProgressDialog(QWidget * const, const progress_bar_value_t &, const QString &) __attribute__((nonnull));
    Q_DISABLE_COPY(TaskProgressDialog)

    void register_new_kiojob(const QPointer<KIO::Job> &, const QString &) __attribute__((always_inline));

private:
    Q_OBJECT
    KSqueezedTextLabel description_label1, description_label2, description_label3;
    QLabel speed_label;
    QProgressBar operation_progress_bar, task_progress_bar;
    progress_bar_value_t step;
    static constexpr progress_bar_value_t step_weight = 100;

private slots:
    void update_kiojob_speed(KJob *, const ulong &);
    void update_progress_bars(KJob *, const ulong &);
};

inline void TaskProgressDialog::register_new_kiojob(const QPointer<KIO::Job> &kiojob, const QString &description)
{
    connect(kiojob, SIGNAL(percent(KJob*,ulong)), this, SLOT(update_progress_bars(KJob*,ulong)), Qt::DirectConnection);
    connect(kiojob, SIGNAL(speed(KJob*,ulong)), this, SLOT(update_kiojob_speed(KJob*,ulong)), Qt::DirectConnection);
    connect(this, &TaskProgressDialog::rejected, kiojob, [&]{kiojob->kill(KIO::Job::EmitResult);}, Qt::DirectConnection);
    const QStringList &description_parts = description.split(QLatin1Char('\n'));
    switch (description_parts.size()) {
    case 1:
        description_label1.clear();
        description_label2.setText(description_parts.first());
        description_label3.clear();
        break;
    case 2:
        description_label1.setText(description_parts.first());
        description_label2.setText(description_parts[1]);
        description_label3.clear();
        break;
    case 3:
        description_label1.setText(description_parts.first());
        description_label2.setText(description_parts[1]);
        description_label3.setText(description_parts.last());
        break;
    default:
        FATAL_BUG;
    }
    speed_label.clear();
    task_progress_bar.reset();
    step += step_weight;
}
