/*
    Copyright (c) 2009 Volker Krause <vkrause@kde.org>
    Copyright (c) 2010 Tom Albers <toma@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "providerpage.h"
#include "global.h"

#include "accountwizard_debug.h"
#include <QSortFilterProxyModel>
#include <KNSCore/DownloadManager>
#include <KLocalizedString>
#include <QLineEdit>

ProviderPage::ProviderPage(KAssistantDialog *parent)
    : Page(parent)
    , m_model(new QStandardItemModel(this))
    , m_downloadManager(new KNSCore::DownloadManager(this))
{
    ui.setupUi(this);

    mProxy = new QSortFilterProxyModel(this);
    mProxy->setSourceModel(m_model);
    mProxy->setFilterKeyColumn(-1);
    mProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
    ui.listView->setModel(mProxy);
    connect(ui.searchLine, &QLineEdit::textChanged, this, &ProviderPage::slotTextChanged);
    m_fetchItem = new QStandardItem(i18n("Fetching provider list..."));
    m_model->appendRow(m_fetchItem);
    m_fetchItem->setFlags(Qt::NoItemFlags);

    // we can start the search, whenever the user reaches this page, chances
    // are we have the full list.
    connect(m_downloadManager, &KNSCore::DownloadManager::searchResult, this, &ProviderPage::fillModel);
    connect(m_downloadManager, &KNSCore::DownloadManager::entryStatusChanged, this, &ProviderPage::providerStatusChanged);
    m_downloadManager->setSearchOrder(KNSCore::DownloadManager::Alphabetical);

    connect(ui.listView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ProviderPage::selectionChanged);
}

void ProviderPage::startFetchingData()
{
    m_downloadManager->search(0, 100000);
}

void ProviderPage::slotTextChanged(const QString &str)
{
    mProxy->setFilterFixedString(str);
}

void ProviderPage::fillModel(const KNSCore::EntryInternal::List &list)
{
    if (m_fetchItem) {
        m_model->removeRows(m_model->indexFromItem(m_fetchItem).row(), 1);
        m_fetchItem = nullptr;
    }

    // KNS3::Entry::Entry() is private, so we need to save the whole list.
    // we can not use a QHash or whatever, as that needs that constructor...
    m_providerEntries = list;

    for (const KNSCore::EntryInternal &e : list) {
        qCDebug(ACCOUNTWIZARD_LOG) << "Found Entry: " << e.name();

        QStandardItem *item = new QStandardItem(e.name());
        item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
        item->setData(e.name(), Qt::ToolTipRole);
        item->setData(e.uniqueId(), Qt::UserRole);
        item->setData(e.providerId(), Qt::UserRole + 1);
        m_model->appendRow(item);
    }
}

void ProviderPage::selectionChanged()
{
    if (ui.listView->selectionModel()->hasSelection()) {
        setValid(true);
    } else {
        setValid(false);
    }
}

void ProviderPage::leavePageNext()
{
    m_newPageReady = false;
    if (!ui.listView->selectionModel()->hasSelection()) {
        return;
    }
    const QModelIndex index = ui.listView->selectionModel()->selectedIndexes().at(0);
    if (!index.isValid()) {
        return;
    }

    const QSortFilterProxyModel *proxy = static_cast<const QSortFilterProxyModel *>(ui.listView->model());
    const QStandardItem *item = m_model->itemFromIndex(proxy->mapToSource(index));
    qCDebug(ACCOUNTWIZARD_LOG) << "Item selected:" << item->text();

    // download and execute it...
    foreach (const KNSCore::EntryInternal &e, m_providerEntries) {
        if (e.uniqueId() == item->data(Qt::UserRole)
            && e.providerId() == item->data(Qt::UserRole + 1)) {
            m_wantedProvider.entryId = e.uniqueId();
            m_wantedProvider.entryProviderId = e.providerId();

            if (e.status() == KNS3::Entry::Installed) {
                qCDebug(ACCOUNTWIZARD_LOG) << "already installed" << e.installedFiles();
                findDesktopAndSetAssistant(e.installedFiles());
            } else {
                qCDebug(ACCOUNTWIZARD_LOG) << "Starting download for " << e.name();
                m_downloadManager->installEntry(e);
            }

            break;
        }
    }
}

void ProviderPage::providerStatusChanged(const KNSCore::EntryInternal &e)
{
    qCDebug(ACCOUNTWIZARD_LOG) << e.name();
    if (e.uniqueId() == m_wantedProvider.entryId
        && e.providerId() == m_wantedProvider.entryProviderId
        && e.status() == KNS3::Entry::Installed) {
        findDesktopAndSetAssistant(e.installedFiles());
    }
}

void ProviderPage::findDesktopAndSetAssistant(const QStringList &list)
{
    for (const QString &file : list) {
        qCDebug(ACCOUNTWIZARD_LOG) << file;
        if (file.endsWith(QLatin1String(".desktop"))) {
            qCDebug(ACCOUNTWIZARD_LOG) << "Yay, a desktop file!" << file;
            Global::setAssistant(file);
            m_newPageReady = true;
            if (m_newPageWanted) {
                qCDebug(ACCOUNTWIZARD_LOG) << "New page was already requested, now we are done, approve it";
                Q_EMIT leavePageNextOk();
            }
            break;
        }
    }
}

QTreeView *ProviderPage::treeview() const
{
    return ui.listView;
}

void ProviderPage::leavePageBackRequested()
{
    Q_EMIT leavePageBackOk();
    Q_EMIT ghnsNotWanted();
}

void ProviderPage::leavePageNextRequested()
{
    m_newPageWanted = true;
    if (m_newPageReady) {
        qCDebug(ACCOUNTWIZARD_LOG) << "New page requested and we are done, so ok...";
        Q_EMIT leavePageNextOk();
    } else {
        qCDebug(ACCOUNTWIZARD_LOG) << "New page requested, but we are not done yet...";
    }
}
