/*
    GpgPasspageconfigdialog.cpp

    This file is part of GpgPasspatra
    SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
    SPDX-FileContributor: Intevation GmbH

    SPDX-License-Identifier: GPL-2.0-only

    It is derived from KCMultidialog which is:

    SPDX-FileCopyrightText: 2000 Matthias Elter <elter@kde.org>
    SPDX-FileCopyrightText: 2003 Daniel Molkentin <molkentin@kde.org>
    SPDX-FileCopyrightText: 2003, 2006 Matthias Kretz <kretz@kde.org>
    SPDX-FileCopyrightText: 2004 Frans Englich <frans.englich@telia.com>
    SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "gpgpasspageconfigdialog.h"

#include "gpgpassconfigmodule.h"

#include <QDebug>
#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QLocale>
#include <QProcess>
#include <QPushButton>
#include <QUrl>

#include <KLocalizedString>
#include <KMessageBox>
#include <KStandardGuiItem>

#include "kwidgetsaddons_version.h"

using namespace GpgPass::Config;

GpgPassPageConfigDialog::GpgPassPageConfigDialog(QWidget *parent)
    : KPageDialog(parent)
{
    setModal(false);

    QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
    buttonBox->setStandardButtons( // | QDialogButtonBox::RestoreDefaults enable this again when ported to KConfig
        QDialogButtonBox::Cancel //
        | QDialogButtonBox::Apply //
        | QDialogButtonBox::Ok //
        | QDialogButtonBox::Reset);
    KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok());
    KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel());
    // KGuiItem::assign(buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults());
    KGuiItem::assign(buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply());
    KGuiItem::assign(buttonBox->button(QDialogButtonBox::Reset), KStandardGuiItem::reset());
    buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false);
    buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);

    connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &GpgPassPageConfigDialog::slotApplyClicked);
    connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &GpgPassPageConfigDialog::slotOkClicked);
    connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &GpgPassPageConfigDialog::slotDefaultClicked);
    connect(buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked, this, &GpgPassPageConfigDialog::slotUser1Clicked);

    setButtonBox(buttonBox);

    connect(this, &KPageDialog::currentPageChanged, this, &GpgPassPageConfigDialog::slotCurrentPageChanged);
}

void GpgPassPageConfigDialog::slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *previous)
{
    if (!previous) {
        return;
    }
    blockSignals(true);
    setCurrentPage(previous);

    auto previousModule = qobject_cast<GpgPassConfigModule *>(previous->widget());
    bool canceled = false;
    if (previousModule && mChangedModules.contains(previousModule)) {
        const int queryUser = KMessageBox::warningTwoActionsCancel(this,
                                                                   i18n("The settings of the current module have changed.\n"
                                                                        "Do you want to apply the changes or discard them?"),
                                                                   i18nc("@title:window", "Apply Settings"),
                                                                   KStandardGuiItem::apply(),
                                                                   KStandardGuiItem::discard(),
                                                                   KStandardGuiItem::cancel());
        if (queryUser == KMessageBox::ButtonCode::PrimaryAction) {
            previousModule->save();
        } else if (queryUser == KMessageBox::ButtonCode::SecondaryAction) {
            previousModule->load();
        }
        canceled = queryUser == KMessageBox::Cancel;
    }
    if (!canceled) {
        mChangedModules.remove(previousModule);
        setCurrentPage(current);
    }
    blockSignals(false);

    clientChanged();
}

void GpgPassPageConfigDialog::apply()
{
    QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply);
    applyButton->setFocus();
    for (const auto &module : std::as_const(mChangedModules)) {
        module->save();
    }
    mChangedModules.clear();
    Q_EMIT configCommitted();
    clientChanged();
}

void GpgPassPageConfigDialog::slotDefaultClicked()
{
    const KPageWidgetItem *item = currentPage();
    if (!item) {
        return;
    }

    auto module = qobject_cast<GpgPassConfigModule *>(item->widget());
    if (!module) {
        return;
    }
    module->defaults();
    clientChanged();
}

void GpgPassPageConfigDialog::slotUser1Clicked()
{
    const KPageWidgetItem *item = currentPage();
    if (!item) {
        return;
    }

    auto module = qobject_cast<GpgPassConfigModule *>(item->widget());
    if (!module) {
        return;
    }
    module->load();
    mChangedModules.remove(module);
    clientChanged();
}

void GpgPassPageConfigDialog::slotApplyClicked()
{
    apply();
}

void GpgPassPageConfigDialog::slotOkClicked()
{
    apply();
    accept();
}

KPageWidgetItem *GpgPassPageConfigDialog::addModule(const QString &name,
                                                    const QString &docPath,
                                                    const QString &icon,
                                                    const QList<QAction *> actions,
                                                    GpgPassConfigModule *module)
{
    mModules << module;
    module->load();
    auto item = addPage(module, name);
    item->setIcon(QIcon::fromTheme(icon));
#if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(6, 6, 0)
    item->setActions(actions);
#else
    Q_UNUSED(actions);
#endif
    connect(module, &GpgPassConfigModule::changed, this, [this, module]() {
        moduleChanged(true);
        mChangedModules.insert(module);
    });
    mHelpUrls.insert(name, docPath);
    return item;
}

void GpgPassPageConfigDialog::moduleChanged(bool state)
{
    auto module = qobject_cast<GpgPassConfigModule *>(sender());
    qDebug() << "Module changed: " << state << " mod " << module;
    if (mChangedModules.contains(module)) {
        if (!state) {
            mChangedModules.remove(module);
        } else {
            return;
        }
    }
    if (state) {
        mChangedModules << module;
    }
    clientChanged();
}

void GpgPassPageConfigDialog::clientChanged()
{
    const KPageWidgetItem *item = currentPage();
    if (!item) {
        return;
    }
    auto module = qobject_cast<GpgPassConfigModule *>(currentPage()->widget());

    if (!module) {
        return;
    }
    qDebug() << "Client changed: "
             << " mod " << module;

    bool change = mChangedModules.contains(module);

    QPushButton *resetButton = buttonBox()->button(QDialogButtonBox::Reset);
    if (resetButton) {
        resetButton->setEnabled(change);
    }

    QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply);
    if (applyButton) {
        applyButton->setEnabled(change);
    }
}

#include "moc_gpgpasspageconfigdialog.cpp"
