/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qhelpindexwidget.h"
#include "qhelpenginecore.h"
#include "qhelpengine_p.h"
#include "qhelpdbreader_p.h"
#include "qhelpcollectionhandler_p.h"

#include <QtCore/QThread>
#include <QtCore/QMutex>
#include <QtHelp/QHelpLink>
#include <QtWidgets/QListView>
#include <QtWidgets/QHeaderView>

#include <algorithm>

QT_BEGIN_NAMESPACE

class QHelpIndexProvider : public QThread
{
public:
    QHelpIndexProvider(QHelpEnginePrivate *helpEngine);
    ~QHelpIndexProvider() override;
    void collectIndices(const QString &customFilterName);
    void stopCollecting();
    QStringList indices() const;

private:
    void run() override;

    QHelpEnginePrivate *m_helpEngine;
    QString m_currentFilter;
    QStringList m_filterAttributes;
    QStringList m_indices;
    mutable QMutex m_mutex;
};

class QHelpIndexModelPrivate
{
public:
    QHelpIndexModelPrivate(QHelpEnginePrivate *hE)
        : helpEngine(hE),
          indexProvider(new QHelpIndexProvider(helpEngine))
    {
    }

    QHelpEnginePrivate *helpEngine;
    QHelpIndexProvider *indexProvider;
    QStringList indices;
};

QHelpIndexProvider::QHelpIndexProvider(QHelpEnginePrivate *helpEngine)
    : QThread(helpEngine),
      m_helpEngine(helpEngine)
{
}

QHelpIndexProvider::~QHelpIndexProvider()
{
    stopCollecting();
}

void QHelpIndexProvider::collectIndices(const QString &customFilterName)
{
    m_mutex.lock();
    m_currentFilter = customFilterName;
    m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName);
    m_mutex.unlock();

    if (isRunning())
        stopCollecting();
    start(LowPriority);
}

void QHelpIndexProvider::stopCollecting()
{
    if (!isRunning())
        return;
    wait();
}

QStringList QHelpIndexProvider::indices() const
{
    QMutexLocker lck(&m_mutex);
    return m_indices;
}

void QHelpIndexProvider::run()
{
    m_mutex.lock();
    const QString currentFilter = m_currentFilter;
    const QStringList attributes = m_filterAttributes;
    const QString collectionFile = m_helpEngine->collectionHandler->collectionFile();
    m_indices = QStringList();
    m_mutex.unlock();

    if (collectionFile.isEmpty())
        return;

    QHelpCollectionHandler collectionHandler(collectionFile);
    collectionHandler.setReadOnly(true);
    if (!collectionHandler.openCollectionFile())
        return;

    const QStringList result = m_helpEngine->usesFilterEngine
            ? collectionHandler.indicesForFilter(currentFilter)
            : collectionHandler.indicesForFilter(attributes);

    m_mutex.lock();
    m_indices = result;
    m_mutex.unlock();
}

/*!
    \class QHelpIndexModel
    \since 4.4
    \inmodule QtHelp
    \brief The QHelpIndexModel class provides a model that
    supplies index keywords to views.


*/

/*!
    \fn void QHelpIndexModel::indexCreationStarted()

    This signal is emitted when the creation of a new index
    has started. The current index is invalid from this
    point on until the signal indexCreated() is emitted.

    \sa isCreatingIndex()
*/

/*!
    \fn void QHelpIndexModel::indexCreated()

    This signal is emitted when the index has been created.
*/

QHelpIndexModel::QHelpIndexModel(QHelpEnginePrivate *helpEngine)
    : QStringListModel(helpEngine)
{
    d = new QHelpIndexModelPrivate(helpEngine);

    connect(d->indexProvider, &QThread::finished,
            this, &QHelpIndexModel::insertIndices);
}

QHelpIndexModel::~QHelpIndexModel()
{
    delete d;
}

/*!
    Creates a new index by querying the help system for
    keywords for the specified \a customFilterName.
*/
void QHelpIndexModel::createIndex(const QString &customFilterName)
{
    const bool running = d->indexProvider->isRunning();
    d->indexProvider->collectIndices(customFilterName);
    if (running)
        return;

    d->indices = QStringList();
    filter(QString());
    emit indexCreationStarted();
}

void QHelpIndexModel::insertIndices()
{
    if (d->indexProvider->isRunning())
        return;

    d->indices = d->indexProvider->indices();
    filter(QString());
    emit indexCreated();
}

/*!
    Returns true if the index is currently built up, otherwise
    false.
*/
bool QHelpIndexModel::isCreatingIndex() const
{
    return d->indexProvider->isRunning();
}

/*!
    \since 5.15

    Returns the associated help engine that manages this model.
*/
QHelpEngineCore *QHelpIndexModel::helpEngine() const
{
    return d->helpEngine->q;
}

#if QT_DEPRECATED_SINCE(5, 15)
/*!
    \obsolete
    Use QHelpEngineCore::documentsForKeyword() instead.
*/
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
QMap<QString, QUrl> QHelpIndexModel::linksForKeyword(const QString &keyword) const
{
    return d->helpEngine->q->linksForKeyword(keyword);
}
QT_WARNING_POP
#endif

/*!
    Filters the indices and returns the model index of the best
    matching keyword. In a first step, only the keywords containing
    \a filter are kept in the model's index list. Analogously, if
    \a wildcard is not empty, only the keywords matched are left
    in the index list. In a second step, the best match is
    determined and its index model returned. When specifying a
    wildcard expression, the \a filter string is used to
    search for the best match.
*/
QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildcard)
{
    if (filter.isEmpty()) {
        setStringList(d->indices);
        return index(-1, 0, QModelIndex());
    }

    QStringList lst;
    int goodMatch = -1;
    int perfectMatch = -1;

    if (!wildcard.isEmpty()) {
        const QRegExp regExp(wildcard, Qt::CaseInsensitive, QRegExp::Wildcard);
        for (const QString &index : qAsConst(d->indices)) {
            if (index.contains(regExp)) {
                lst.append(index);
                if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) {
                    if (goodMatch == -1)
                        goodMatch = lst.count() - 1;
                    if (filter.length() == index.length()){
                        perfectMatch = lst.count() - 1;
                    }
                } else if (perfectMatch > -1 && index == filter) {
                    perfectMatch = lst.count() - 1;
                }
            }
        }
    } else {
        for (const QString &index : qAsConst(d->indices)) {
            if (index.contains(filter, Qt::CaseInsensitive)) {
                lst.append(index);
                if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) {
                    if (goodMatch == -1)
                        goodMatch = lst.count() - 1;
                    if (filter.length() == index.length()){
                        perfectMatch = lst.count() - 1;
                    }
                } else if (perfectMatch > -1 && index == filter) {
                    perfectMatch = lst.count() - 1;
                }
            }
        }

    }

    if (perfectMatch == -1)
        perfectMatch = qMax(0, goodMatch);

    setStringList(lst);
    return index(perfectMatch, 0, QModelIndex());
}



/*!
    \class QHelpIndexWidget
    \inmodule QtHelp
    \since 4.4
    \brief The QHelpIndexWidget class provides a list view
    displaying the QHelpIndexModel.
*/

/*!
    \fn void QHelpIndexWidget::linkActivated(const QUrl &link,
        const QString &keyword)

    \obsolete

    Use documentActivated() instead.

    This signal is emitted when an item is activated and its
    associated \a link should be shown. To know where the link
    belongs to, the \a keyword is given as a second parameter.
*/

/*!
    \fn void QHelpIndexWidget::linksActivated(const QMap<QString, QUrl> &links,
        const QString &keyword)

    \obsolete

    Use documentsActivated() instead.

    This signal is emitted when the item representing the \a keyword
    is activated and the item has more than one link associated.
    The \a links consist of the document titles and their URLs.
*/

/*!
    \fn void QHelpIndexWidget::documentActivated(const QHelpLink &document,
        const QString &keyword)

    \since 5.15

    This signal is emitted when an item is activated and its
    associated \a document should be shown. To know where the link
    belongs to, the \a keyword is given as a second parameter.
*/

/*!
    \fn void QHelpIndexWidget::documentsActivated(const QList<QHelpLink> &documents,
        const QString &keyword)

    \since 5.15

    This signal is emitted when the item representing the \a keyword
    is activated and the item has more than one document associated.
    The \a documents consist of the document titles and their URLs.
*/

QHelpIndexWidget::QHelpIndexWidget()
    : QListView(nullptr)
{
    setEditTriggers(QAbstractItemView::NoEditTriggers);
    setUniformItemSizes(true);
    connect(this, &QAbstractItemView::activated,
            this, &QHelpIndexWidget::showLink);
}

void QHelpIndexWidget::showLink(const QModelIndex &index)
{
    if (!index.isValid())
        return;

    QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model());
    if (!indexModel)
        return;

    const QVariant &v = indexModel->data(index, Qt::DisplayRole);
    const QString name = v.isValid() ? v.toString() : QString();

    const QList<QHelpLink> &docs = indexModel->helpEngine()->documentsForKeyword(name);
    if (docs.count() > 1) {
        emit documentsActivated(docs, name);
        QT_WARNING_PUSH
        QT_WARNING_DISABLE_DEPRECATED
        QMap<QString, QUrl> links;
        for (const auto &doc : docs)
            static_cast<QMultiMap<QString, QUrl> &>(links).insert(doc.title, doc.url);
        emit linksActivated(links, name);
        QT_WARNING_POP
    } else if (!docs.isEmpty()) {
        emit documentActivated(docs.first(), name);
        QT_WARNING_PUSH
        QT_WARNING_DISABLE_DEPRECATED
        emit linkActivated(docs.first().url, name);
        QT_WARNING_POP
    }
}

/*!
    Activates the current item which will result eventually in
    the emitting of a linkActivated() or linksActivated()
    signal.
*/
void QHelpIndexWidget::activateCurrentItem()
{
    showLink(currentIndex());
}

/*!
    Filters the indices according to \a filter or \a wildcard.
    The item with the best match is set as current item.

    \sa QHelpIndexModel::filter()
*/
void QHelpIndexWidget::filterIndices(const QString &filter, const QString &wildcard)
{
    QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model());
    if (!indexModel)
        return;
    const QModelIndex &idx = indexModel->filter(filter, wildcard);
    if (idx.isValid())
        setCurrentIndex(idx);
}

QT_END_NAMESPACE
