 /***********************************************************************
 *                                                                     *
 * 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/> *
 *                                                                     *
 ***********************************************************************/


#include "previewdialog.hxx"
#include "previewdialog.moc"

#include <KLocalizedString>
#include <KStandardGuiItem>
#include <QApplication>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHeaderView>
#include <QPointer>
#include <QVBoxLayout>


PreviewDialog::PreviewDialog(QWidget * const parent, const QString &&source_url_string, const QString &&destination_url_string, const table_row_t &&table_row_n) : QDialog(parent), table(table_row_n, 3)
{
    // Setup widgets
    table.setEditTriggers(QAbstractItemView::NoEditTriggers);
    table.setTextElideMode(Qt::ElideLeft);
    table.setHorizontalHeaderLabels({source_url_string, QString(), destination_url_string});
    table.setSelectionMode(QAbstractItemView::NoSelection);
    table.verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    // ↓
    result_label.setAlignment(Qt::AlignCenter);
    // ↓
    QDialogButtonBox * const button_box = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok);
    connect(button_box, &QDialogButtonBox::accepted, this, &PreviewDialog::accept, Qt::DirectConnection);
    connect(button_box, &QDialogButtonBox::helpRequested, this, &PreviewDialog::show_help, Qt::DirectConnection);
    connect(button_box, &QDialogButtonBox::rejected, this, &PreviewDialog::reject, Qt::DirectConnection);
    // ↓
    QVBoxLayout * const this_layout = new QVBoxLayout(this);
    this_layout->addWidget(&table);
    this_layout->addWidget(&result_label);
    this_layout->addWidget(button_box);

    Q_ASSERT(testAttribute(Qt::WA_DeleteOnClose) == false);
    const QDesktopWidget * const desktop_widget = QApplication::desktop();
    resize(desktop_widget->width()/2, desktop_widget->height()/2);
    setWindowTitle(i18nc("@title:window", "Preview"));
}


void PreviewDialog::add_copy_in_destination(const QIcon &icon, const QString &path, const KIO::filesize_t &size)
{
    bytes_to_write += size;
    append_items_in_table({{new QTableWidgetItem(icon, path), new QTableWidgetItem(copy_icon, plus % KIO::convertSize(size)), new QTableWidgetItem(new_file_icon, QString())}});
}


void PreviewDialog::add_copy_in_source(const QIcon &icon, const QString &path, const KIO::filesize_t &size)
{
    bytes_to_write += size;
    append_items_in_table({{new QTableWidgetItem(new_file_icon, QString()), new QTableWidgetItem(copy_icon, plus % KIO::convertSize(size)), new QTableWidgetItem(icon, path)}});
}


void PreviewDialog::add_del_in_destination(const QIcon &icon, const QString &path, const KIO::filesize_t &size)
{
    bytes_to_delete += size;
    append_items_in_table({{new QTableWidgetItem(), new QTableWidgetItem(del_icon, minus % KIO::convertSize(size)), new QTableWidgetItem(icon, path)}});
}


void PreviewDialog::add_del_in_source(const QIcon &icon, const QString &path, const KIO::filesize_t &size)
{
    bytes_to_delete += size;
    append_items_in_table({{new QTableWidgetItem(icon, path), new QTableWidgetItem(del_icon, minus % KIO::convertSize(size)), new QTableWidgetItem()}});
}


void PreviewDialog::add_mkdir_in_destination(const QString &path)
{
    append_items_in_table({{new QTableWidgetItem(folder_icon, path), new QTableWidgetItem(mkdir_icon, QString()), new QTableWidgetItem(new_dir_icon, QString())}});
}


void PreviewDialog::add_mkdir_in_source(const QString &path)
{
    append_items_in_table({{new QTableWidgetItem(new_dir_icon, QString()), new QTableWidgetItem(mkdir_icon, QString()), new QTableWidgetItem(folder_icon, path)}});
}


void PreviewDialog::add_overwrite_in_destination(const QIcon &icon1, const QIcon &icon2, const QString &path, const KIO::filesize_t &size1, const KIO::filesize_t &size2)
{
    bytes_to_write += size1;
    bytes_to_delete += size2;
    const QString &size_difference = (size2 > size1) ? (minus % KIO::convertSize(size2 - size1)) : (plus % KIO::convertSize(size1 - size2));
    append_items_in_table({{new QTableWidgetItem(icon1, path), new QTableWidgetItem(overwrite_icon, size_difference), new QTableWidgetItem(icon2, path)}});
}


void PreviewDialog::add_overwrite_in_source(const QIcon &icon1, const QIcon &icon2, const QString &path, const KIO::filesize_t &size1, const KIO::filesize_t &size2)
{
    bytes_to_write += size1;
    bytes_to_delete += size2;
    const QString &size_difference = (size2 > size1) ? (minus % KIO::convertSize(size2 - size1)) : (plus % KIO::convertSize(size1 - size2));
    append_items_in_table({{new QTableWidgetItem(icon2, path), new QTableWidgetItem(overwrite_in_source_icon, size_difference), new QTableWidgetItem(icon1, path)}});
}


void PreviewDialog::add_rename_in_destination(const QIcon &icon, const QString &path)
{
    append_items_in_table({{new QTableWidgetItem(), new QTableWidgetItem(rename_icon, QString()), new QTableWidgetItem(icon, path)}});
}


void PreviewDialog::add_rename_in_source(const QIcon &icon, const QString &path)
{
    append_items_in_table({{new QTableWidgetItem(icon, path), new QTableWidgetItem(rename_icon, QString()), new QTableWidgetItem()}});
}


inline void PreviewDialog::append_items_in_table(const std::array<QTableWidgetItem*,3> &&table_widget_item_array)
{
    for (std::size_t i = 0; i < 3; ++i) {
        table_widget_item_array[i]->setFlags(Qt::ItemIsEnabled | Qt::ItemNeverHasChildren);
        table.setItem(current_table_row, table_row_t(i), table_widget_item_array[i]);
    }
    ++current_table_row;
}


void PreviewDialog::showEvent(QShowEvent * const)
{
    QHeaderView * const header = table.horizontalHeader();
    header->setSectionResizeMode(0, QHeaderView::Stretch);
    header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
    header->setSectionResizeMode(2, QHeaderView::Stretch);
    const bool &more_deletions_than_writes = bytes_to_delete > bytes_to_write;
    static const QString &space = QStringLiteral("   ");
    result_label.setText(i18nc("@label", "Final result:") %
                             space %
                             plus % KIO::convertSize(bytes_to_write) %
                             space %
                             minus % KIO::convertSize(bytes_to_delete) %
                             space %
                             QLatin1Char('=') %
                             space %
                             (more_deletions_than_writes ? minus : plus) %
                             KIO::convertSize(more_deletions_than_writes ? (bytes_to_delete - bytes_to_write) : (bytes_to_write - bytes_to_delete)));
}


void PreviewDialog::show_help()
{
    static QPointer<QDialog> help_dialog;
    if (help_dialog.isNull()) {
        help_dialog = new QDialog(this);
        help_dialog->setWindowTitle(KStandardGuiItem::help().text().remove(QLatin1Char('&')));
        QGridLayout * const help_dialog_layout = new QGridLayout(help_dialog);
        int row = 0;
        const auto &add_row_with = [&](const QIcon &icon, const QString &string){
            QLabel * const icon_label = new QLabel;
            icon_label->setPixmap(icon.pixmap(16, 16, QIcon::Normal, QIcon::On));
            help_dialog_layout->addWidget(icon_label, row, 0, 1, 1);
            help_dialog_layout->addWidget(new QLabel(string), row, 1, 1, 1);
            ++row;
        };
        add_row_with(copy_icon, i18nc("@item:intable task", "Copy"));
        add_row_with(del_icon, i18nc("@item:intable task", "Delete/trash"));
        add_row_with(mkdir_icon, i18nc("@item:intable task", "Make a new directory"));
        add_row_with(new_dir_icon, i18nc("@item:intable", "New directory"));
        add_row_with(new_file_icon, i18nc("@item:intable", "New file"));
        add_row_with(overwrite_in_source_icon, i18nc("@item:intable task", "Overwrite source with destination"));
        add_row_with(overwrite_icon, i18nc("@item:intable task", "Overwrite destination with source"));
        add_row_with(rename_icon, i18nc("@item:intable task", "Rename"));
        QDialogButtonBox * const button_box = new QDialogButtonBox(QDialogButtonBox::Ok);
        connect(button_box, &QDialogButtonBox::accepted, help_dialog, &QDialog::close, Qt::DirectConnection);
        help_dialog_layout->addWidget(button_box, row, 0, 1, 2);
        help_dialog_layout->setSizeConstraint(QLayout::SetFixedSize);
    }
    help_dialog->open();
}
