/*
    This file is part of the KDE libraries
    SPDX-FileCopyrightText: 2013 Valentin Rusu <kde@rusu.info>

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

#include "kwalletmanagerwidget.h"
#include "kwalletmanagerwidgetitem.h"
#include "kwallet_interface.h"
#include "kwalletmanager_debug.h"

#include <KLocalizedString>
#include <KMessageBox>
#include <KWallet>
#include <QDragEnterEvent>
#include <QUrl>
#include <QVBoxLayout>

KWalletManagerWidget::KWalletManagerWidget(QWidget *parent, Qt::WindowFlags /*flags*/):
    KPageWidget(parent)
{
    setFaceType(Auto);
    setAcceptDrops(true);

    connect(this, &KWalletManagerWidget::currentPageChanged, this, &KWalletManagerWidget::onCurrentPageChanged);
}

KWalletManagerWidget::~KWalletManagerWidget() = default;

void KWalletManagerWidget::onCurrentPageChanged(KPageWidgetItem */*current*/, KPageWidgetItem */*before*/)
{

}

void KWalletManagerWidget::updateWalletDisplay(const QString &selectWallet /* = QString() */)
{
    // NOTE: this method is called upon several kwalletd events
    static bool alreadyUpdating = false;
    if (alreadyUpdating) {
        return;
    }

    alreadyUpdating = true;
    // find out pages corresponding to deleted wallets
    const QStringList wl = KWallet::Wallet::walletList();
    WalletPagesHash::iterator p = _walletPages.begin();
    while (p != _walletPages.end()) {
        if (!wl.contains(p.key())) {
            // remove the page corresponding to the missing wallet
            removePage(p.value());
            p = _walletPages.erase(p);
        } else {
            ++p;
        }
    }

    // add new wallets
    for (QStringList::const_iterator i = wl.begin(); i != wl.end(); ++i) {
        const QString &name = *i;
        if (!_walletPages.contains(name)) {
            auto wi = new KWalletManagerWidgetItem(this, name);
            addPage(wi);
            _walletPages.insert(*i, wi);
        }
    }

    // update existing wallets display, e.g. icon
    WalletPagesHash::const_iterator cp = _walletPages.constBegin();
    WalletPagesHash::const_iterator cend = _walletPages.constEnd();
    for (; cp != cend; cp++) {
        cp.value()->updateWalletDisplay();
    }

    if (!selectWallet.isEmpty()) {
        setCurrentPage(_walletPages[selectWallet]);
    }
    alreadyUpdating = false;
}

bool KWalletManagerWidget::hasWallet(const QString &name) const
{
    return _walletPages.contains(name);
}

bool KWalletManagerWidget::openWalletFile(const QString &/*path*/)
{
    Q_ASSERT(0);
    // TODO: implement this method: add a new tab with an editor centered on a file
    return false;
}

bool KWalletManagerWidget::openWallet(const QString &name)
{
    bool result = false;
    if (_walletPages.contains(name)) {
        KWalletManagerWidgetItem *wi = _walletPages[name];
        setCurrentPage(wi);
        result = wi->openWallet();
    }
    return result;
}

QString KWalletManagerWidget::activeWalletName() const
{
    auto page = qobject_cast<KWalletManagerWidgetItem *>(currentPage());
    if (page) {
        return page->walletName();
    } else {
        return {};
    }
}

void KWalletManagerWidget::dragEnterEvent(QDragEnterEvent *e)
{
    if (e->mimeData()->hasFormat(QStringLiteral("application/x-kwallet-wallet"))) {
        e->accept();
    } else {
        e->ignore();
    }
}

void KWalletManagerWidget::dragMoveEvent(QDragMoveEvent */*e*/)
{
    qCDebug(KWALLETMANAGER_LOG) << "KWalletManagerWidget::dragMoveEvent";
//     KUrl dummy;
//     QListWidgetItem *dummy2;
//     if (shouldIgnoreDropEvent(e, &dummy, &dummy2)) {
//         e->ignore();
//     } else {
//         e->accept();
//     }
}

void KWalletManagerWidget::dropEvent(QDropEvent */*e*/)
{
    qCDebug(KWALLETMANAGER_LOG) << "KWalletManagerWidget::dropEvent";
//     KUrl u;
//     QListWidgetItem *item;
//     if (shouldIgnoreDropEvent(e, &u, &item)) {
//         e->ignore();
//         return;
//     }
//
//     if (!item) {
//         // Not dropped over an item thus it is a wallet
//         const QString dest = KGlobal::dirs()->saveLocation("kwallet") + u.fileName();
//         if (QFile::exists(dest)) {
//             KMessageBox::error(viewport(), i18n("That wallet file already exists.  You cannot overwrite wallets."));
//             e->ignore();
//             return;
//         }
//
//         // FIXME: verify that it is a real wallet file first
//         KIO::NetAccess::file_copy(u, KUrl(dest));
//         e->accept();
//     } else {
//         // Dropped over an item thus it is a folder
//         KWalletItem *kwi = dynamic_cast<KWalletItem *>(item);
//         Q_ASSERT(kwi);
//         if (kwi) {
//             kwi->processDropEvent(e);
//         }
//     }
}

bool KWalletManagerWidget::shouldIgnoreDropEvent(const QDropEvent */*e*/, QUrl */*u*/) const
{
    return false;
//     if (e->source() == viewport()) {
//         return true;
//     }
//
//     if (!e->provides("application/x-kwallet-folder") &&
//         !e->provides("application/x-kwallet-wallet") &&
//         !e->provides("text/uri-list")) {
//         return true;
//     }
//
//     // Over wallets folders, over nothing wallets
//     *item = itemAt(e->pos());
//     const QByteArray edata = e->encodedData(item ? "application/x-kwallet-folder" : "application/x-kwallet-wallet");
//     *u = decodeUrl(edata);
//     if (*u == KUrl()) {
//         *u = decodeUrl(e->encodedData("text/uri-list"));
//     }
//
//     return *u == KUrl();
}

bool KWalletManagerWidget::hasUnsavedChanges(const QString &name) const
{
    if (name.isEmpty()) {
        WalletPagesHash::const_iterator cp   = _walletPages.constBegin();
        WalletPagesHash::const_iterator cend = _walletPages.constEnd();
        for (; cp != cend; ++cp) {
            if (cp.value()->hasUnsavedChanges()) {
                return true;
            }
        }
        return false;
    } else {
        WalletPagesHash::const_iterator it = _walletPages.find(name);
        if (it == _walletPages.constEnd()) {
                return false;
        }
        return it.value()->hasUnsavedChanges();
    }
}

void KWalletManagerWidget::setErrorMessage(const QString &message) {
    if (!_walletPages.isEmpty()) {
        return;
    }

    if (_errorItem == nullptr) {
        auto placeholderWidget = new QWidget();

        auto layout = new QVBoxLayout();
        placeholderWidget->setLayout(layout);

        _errorLabel =
            new QLabel(xi18nc("@info:status",
                "An error occurred when connecting to the KWallet service:<nl/>%1",
                message));
        _errorLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
        layout->addWidget(_errorLabel);

        _errorItem = new KPageWidgetItem(placeholderWidget);
    }

    addPage(_errorItem);
    setCurrentPage(_errorItem);
}

#include "moc_kwalletmanagerwidget.cpp"
