/****************************************************************************
**
** Copyright (C) 2014 Aaron McCarthy <mccarthy.aaron@gmail.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** 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 http://www.qt.io/terms-conditions. For further
** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativesupportedcategoriesmodel_p.h"
#include "qdeclarativeplaceicon_p.h"
#include "qgeoserviceprovider.h"
#include "error_messages_p.h"
#include <QtCore/private/qobject_p.h>

#include <QCoreApplication>
#include <QtQml/QQmlInfo>
#include <QtLocation/QPlaceManager>
#include <QtLocation/QPlaceIcon>

QT_BEGIN_NAMESPACE

/*!
    \qmltype CategoryModel
    \instantiates QDeclarativeSupportedCategoriesModel
    \inqmlmodule QtLocation
    \ingroup qml-QtLocation5-places
    \ingroup qml-QtLocation5-places-models
    \since QtLocation 5.5

    \brief The CategoryModel type provides a model of the categories supported by a \l Plugin.

    The CategoryModel type provides a model of the categories that are available from the
    current \l Plugin.  The model supports both a flat list of categories and a hierarchical tree
    representing category groupings.  This can be controlled by the \l hierarchical property.

    The model supports the following roles:

    \table
        \header
            \li Role
            \li Type
            \li Description
        \row
            \li category
            \li \l Category
            \li Category object for the current item.
      \row
            \li parentCategory
            \li \l Category
            \li Parent category object for the current item.
                If there is no parent, null is returned.
    \endtable

    The following example displays a flat list of all available categories:

    \snippet declarative/places.qml QtQuick import
    \snippet declarative/maps.qml QtLocation import
    \codeline
    \snippet declarative/places.qml CategoryView

    To access the hierarchical category model it is necessary to use a \l DelegateModel to access
    the child items.
*/

/*!
    \qmlproperty Plugin CategoryModel::plugin

    This property holds the provider \l Plugin used by this model.
*/

/*!
    \qmlproperty bool CategoryModel::hierarchical

    This property holds whether the model provides a hierarchical tree of categories or a flat
    list.  The default is true.
*/

/*!
    \qmlmethod string QtLocation::CategoryModel::data(ModelIndex index, int role)
    \internal

    This method retrieves the model's data per \a index and \a role.
*/

/*!
    \qmlmethod string QtLocation::CategoryModel::errorString() const

    This read-only property holds the textual presentation of the latest category model error.
    If no error has occurred, an empty string is returned.

    An empty string may also be returned if an error occurred which has no associated
    textual representation.
*/

/*!
    \qmlmethod void QtLocation::CategoryModel::update()
    \internal

    Updates the model.

    \note The CategoryModel auto updates automatically when needed. Calling this method explicitly is normally not necessary.
*/

/*!
    \internal
    \enum QDeclarativeSupportedCategoriesModel::Roles
*/

QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObject *parent)
:   QAbstractItemModel(parent), m_response(0), m_plugin(0), m_hierarchical(true),
    m_complete(false), m_status(Null)
{
}

QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel()
{
    qDeleteAll(m_categoriesTree);
}

/*!
    \internal
*/
// From QQmlParserStatus
void QDeclarativeSupportedCategoriesModel::componentComplete()
{
    m_complete = true;
    if (m_plugin) // do not try to load or change status when trying to update in componentComplete() if the plugin hasn't been set yet even once.
        update();
}

/*!
    \internal
*/
int QDeclarativeSupportedCategoriesModel::rowCount(const QModelIndex &parent) const
{
    if (m_categoriesTree.keys().isEmpty())
        return 0;

    PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(parent.internalPointer());
    if (!node)
        node = m_categoriesTree.value(QString());
    else if (m_categoriesTree.keys(node).isEmpty())
        return 0;

    return node->childIds.count();
}

/*!
    \internal
*/
int QDeclarativeSupportedCategoriesModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return 1;
}

/*!
    \internal
*/
QModelIndex QDeclarativeSupportedCategoriesModel::index(int row, int column, const QModelIndex &parent) const
{
    if (column != 0 || row < 0)
        return QModelIndex();

    PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(parent.internalPointer());

    if (!node)
        node = m_categoriesTree.value(QString());
    else if (m_categoriesTree.keys(node).isEmpty()) //return root index if parent is non-existent
        return QModelIndex();

    if (row > node->childIds.count())
        return QModelIndex();

    QString id = node->childIds.at(row);
    Q_ASSERT(m_categoriesTree.contains(id));

    return createIndex(row, 0, m_categoriesTree.value(id));
}

/*!
    \internal
*/
QModelIndex QDeclarativeSupportedCategoriesModel::parent(const QModelIndex &child) const
{
    PlaceCategoryNode *childNode = static_cast<PlaceCategoryNode *>(child.internalPointer());
    if (m_categoriesTree.keys(childNode).isEmpty())
        return QModelIndex();

    return index(childNode->parentId);
}

/*!
    \internal
*/
QVariant QDeclarativeSupportedCategoriesModel::data(const QModelIndex &index, int role) const
{
    PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(index.internalPointer());
    if (!node)
        node = m_categoriesTree.value(QString());
    else if (m_categoriesTree.keys(node).isEmpty())
        return QVariant();

   QDeclarativeCategory *category = node->declCategory.data();

    switch (role) {
    case Qt::DisplayRole:
        return category->name();
    case CategoryRole:
        return QVariant::fromValue(category);
    case ParentCategoryRole: {
        if (!m_categoriesTree.keys().contains(node->parentId))
            return QVariant();
        else
            return QVariant::fromValue(m_categoriesTree.value(node->parentId)->declCategory.data());
    }
    default:
        return QVariant();
    }
}

QHash<int, QByteArray> QDeclarativeSupportedCategoriesModel::roleNames() const
{
    QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
    roles.insert(CategoryRole, "category");
    roles.insert(ParentCategoryRole, "parentCategory");
    return roles;
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
{
    if (m_plugin == plugin)
        return;

    //disconnect the manager of the old plugin if we have one
    if (m_plugin) {
        disconnect(m_plugin, nullptr, this, nullptr);
        QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
        if (serviceProvider) {
            QPlaceManager *placeManager = serviceProvider->placeManager();
            if (placeManager) {
                disconnect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)),
                           this, SLOT(addedCategory(QPlaceCategory,QString)));
                disconnect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)),
                           this, SLOT(updatedCategory(QPlaceCategory,QString)));
                disconnect(placeManager, SIGNAL(categoryRemoved(QString,QString)),
                           this, SLOT(removedCategory(QString,QString)));
                disconnect(placeManager, SIGNAL(dataChanged()),
                           this, SIGNAL(dataChanged()));
            }
        }
    }

    m_plugin = plugin;

    // handle plugin attached changes -> update categories
    if (m_plugin) {
        if (m_plugin->isAttached()) {
            connectNotificationSignals();
            update();
        } else {
            connect(m_plugin, &QDeclarativeGeoServiceProvider::attached, this, &QDeclarativeSupportedCategoriesModel::update);
            connect(m_plugin, &QDeclarativeGeoServiceProvider::attached, this, &QDeclarativeSupportedCategoriesModel::connectNotificationSignals);
        }
    }

    if (m_complete)
        emit pluginChanged();
}

/*!
    \internal
*/
QDeclarativeGeoServiceProvider *QDeclarativeSupportedCategoriesModel::plugin() const
{
    return m_plugin;
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::setHierarchical(bool hierarchical)
{
    if (m_hierarchical == hierarchical)
        return;

    m_hierarchical = hierarchical;
    emit hierarchicalChanged();

    updateLayout();
}

/*!
    \internal
*/
bool QDeclarativeSupportedCategoriesModel::hierarchical() const
{
    return m_hierarchical;
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::replyFinished()
{
    if (!m_response)
        return;

    m_response->deleteLater();

    if (m_response->error() == QPlaceReply::NoError) {
        m_errorString.clear();

        m_response = 0;

        updateLayout();
        setStatus(QDeclarativeSupportedCategoriesModel::Ready);
    } else {
        const QString errorString = m_response->errorString();

        m_response = 0;

        setStatus(Error, errorString);
    }
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::addedCategory(const QPlaceCategory &category,
                                                         const QString &parentId)
{
    if (m_response)
        return;

    if (!m_categoriesTree.contains(parentId))
        return;

    if (category.categoryId().isEmpty())
        return;

    PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
    if (!parentNode)
        return;

    int rowToBeAdded = rowToAddChild(parentNode, category);
    QModelIndex parentIndex = index(parentId);
    beginInsertRows(parentIndex, rowToBeAdded, rowToBeAdded);
    PlaceCategoryNode *categoryNode = new PlaceCategoryNode;
    categoryNode->parentId = parentId;
    categoryNode->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(category, m_plugin, this));

    m_categoriesTree.insert(category.categoryId(), categoryNode);
    parentNode->childIds.insert(rowToBeAdded,category.categoryId());
    endInsertRows();

    //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel
    //does not get updated when a child is added to a model
    beginResetModel();
    endResetModel();
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::updatedCategory(const QPlaceCategory &category,
                                                           const QString &parentId)
{
    if (m_response)
        return;

    QString categoryId = category.categoryId();

    if (!m_categoriesTree.contains(parentId))
        return;

    if (category.categoryId().isEmpty() || !m_categoriesTree.contains(categoryId))
        return;

    PlaceCategoryNode *newParentNode = m_categoriesTree.value(parentId);
    if (!newParentNode)
        return;

    PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
    if (!categoryNode)
        return;

    categoryNode->declCategory->setCategory(category);

    if (categoryNode->parentId == parentId) { //reparenting to same parent
        QModelIndex parentIndex = index(parentId);
        int rowToBeAdded = rowToAddChild(newParentNode, category);
        int oldRow = newParentNode->childIds.indexOf(categoryId);

        //check if we are changing the position of the category
        if (qAbs(rowToBeAdded - newParentNode->childIds.indexOf(categoryId)) > 1) {
            //if the position has changed we are moving rows
            beginMoveRows(parentIndex, oldRow, oldRow,
                          parentIndex, rowToBeAdded);

            newParentNode->childIds.removeAll(categoryId);
            newParentNode->childIds.insert(rowToBeAdded, categoryId);
            endMoveRows();
        } else {// if the position has not changed we modifying an existing row
            QModelIndex categoryIndex = index(categoryId);
            emit dataChanged(categoryIndex, categoryIndex);
        }
    } else { //reparenting to different parents
        QPlaceCategory oldCategory = categoryNode->declCategory->category();
        PlaceCategoryNode *oldParentNode = m_categoriesTree.value(categoryNode->parentId);
        if (!oldParentNode)
            return;
        QModelIndex oldParentIndex = index(categoryNode->parentId);
        QModelIndex newParentIndex = index(parentId);

        int rowToBeAdded = rowToAddChild(newParentNode, category);
        beginMoveRows(oldParentIndex, oldParentNode->childIds.indexOf(categoryId),
                      oldParentNode->childIds.indexOf(categoryId), newParentIndex, rowToBeAdded);
        oldParentNode->childIds.removeAll(oldCategory.categoryId());
        newParentNode->childIds.insert(rowToBeAdded, categoryId);
        categoryNode->parentId = parentId;
        endMoveRows();

        //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel
        //does not get updated when an index is updated to contain children
        beginResetModel();
        endResetModel();
    }
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::removedCategory(const QString &categoryId, const QString &parentId)
{
    if (m_response)
        return;

    if (!m_categoriesTree.contains(categoryId) || !m_categoriesTree.contains(parentId))
        return;

    QModelIndex parentIndex = index(parentId);
    QModelIndex categoryIndex = index(categoryId);

    beginRemoveRows(parentIndex, categoryIndex.row(), categoryIndex.row());
    PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
    parentNode->childIds.removeAll(categoryId);
    delete m_categoriesTree.take(categoryId);
    endRemoveRows();
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::connectNotificationSignals()
{
    if (!m_plugin)
        return;

    QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
    if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError)
        return;

    QPlaceManager *placeManager = serviceProvider->placeManager();
    if (!placeManager)
        return;

    // listen for any category notifications so that we can reupdate the categories
    // model.
    connect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)),
            this, SLOT(addedCategory(QPlaceCategory,QString)));
    connect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)),
            this, SLOT(updatedCategory(QPlaceCategory,QString)));
    connect(placeManager, SIGNAL(categoryRemoved(QString,QString)),
            this, SLOT(removedCategory(QString,QString)));
    connect(placeManager, SIGNAL(dataChanged()),
            this, SIGNAL(dataChanged()));
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::update()
{
    if (!m_complete)
        return;

    if (m_response)
        return;

    setStatus(Loading);

    if (!m_plugin) {
        updateLayout();
        setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
        return;
    }

    QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
    if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError) {
        updateLayout();
        setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR)
                         .arg(m_plugin->name()));
        return;
    }

    QPlaceManager *placeManager = serviceProvider->placeManager();
    if (!placeManager) {
        updateLayout();
        setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
                         .arg(m_plugin->name()).arg(serviceProvider->errorString()));
        return;
    }

    m_response = placeManager->initializeCategories();
    if (m_response) {
        connect(m_response, SIGNAL(finished()), this, SLOT(replyFinished()));
    } else {
        updateLayout();
        setStatus(Error, QCoreApplication::translate(CONTEXT_NAME,
                    CATEGORIES_NOT_INITIALIZED));
    }
}

/*!
    \internal
*/
void QDeclarativeSupportedCategoriesModel::updateLayout()
{
    beginResetModel();
    qDeleteAll(m_categoriesTree);
    m_categoriesTree.clear();

    if (m_plugin) {
        QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
        if (serviceProvider && serviceProvider->error() == QGeoServiceProvider::NoError) {
            QPlaceManager *placeManager = serviceProvider->placeManager();
            if (placeManager) {
                PlaceCategoryNode *node = new PlaceCategoryNode;
                node->childIds = populateCategories(placeManager, QPlaceCategory());
                m_categoriesTree.insert(QString(), node);
                node->declCategory = QSharedPointer<QDeclarativeCategory>
                    (new QDeclarativeCategory(QPlaceCategory(), m_plugin, this));
            }
        }
    }

    endResetModel();
}

QString QDeclarativeSupportedCategoriesModel::errorString() const
{
    return m_errorString;
}

/*!
    \qmlproperty enumeration CategoryModel::status

    This property holds the status of the model.  It can be one of:

    \table
        \row
            \li CategoryModel.Null
            \li No category fetch query has been executed.  The model is empty.
        \row
            \li CategoryModel.Ready
            \li No error occurred during the last operation, further operations may be performed on
               the model.
        \row
            \li CategoryModel.Loading
            \li The model is being updated, no other operations may be performed until complete.
        \row
            \li CategoryModel.Error
            \li An error occurred during the last operation, further operations can still be
               performed on the model.
    \endtable
*/
void QDeclarativeSupportedCategoriesModel::setStatus(Status status, const QString &errorString)
{
    Status originalStatus = m_status;
    m_status = status;
    m_errorString = errorString;

    if (originalStatus != m_status)
        emit statusChanged();
}

QDeclarativeSupportedCategoriesModel::Status QDeclarativeSupportedCategoriesModel::status() const
{
    return m_status;
}

/*!
    \internal
*/
QStringList QDeclarativeSupportedCategoriesModel::populateCategories(QPlaceManager *manager, const QPlaceCategory &parent)
{
    Q_ASSERT(manager);

    QStringList childIds;

    const auto byName = [](const QPlaceCategory &lhs, const QPlaceCategory &rhs) {
        return lhs.name() < rhs.name();
    };

    auto categories = manager->childCategories(parent.categoryId());
    std::sort(categories.begin(), categories.end(), byName);

    for (const auto &category : qAsConst(categories)) {
        auto node = new PlaceCategoryNode;
        node->parentId = parent.categoryId();
        node->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(category, m_plugin ,this));

        if (m_hierarchical)
            node->childIds = populateCategories(manager, category);

        m_categoriesTree.insert(node->declCategory->categoryId(), node);
        childIds.append(category.categoryId());

        if (!m_hierarchical) {
            childIds.append(populateCategories(manager,node->declCategory->category()));
        }
    }
    return childIds;
}

/*!
    \internal
*/
QModelIndex QDeclarativeSupportedCategoriesModel::index(const QString &categoryId) const
{
    if (categoryId.isEmpty())
        return QModelIndex();

    if (!m_categoriesTree.contains(categoryId))
        return QModelIndex();

    PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
    if (!categoryNode)
        return QModelIndex();

    QString parentCategoryId = categoryNode->parentId;

    PlaceCategoryNode *parentNode = m_categoriesTree.value(parentCategoryId);

    return createIndex(parentNode->childIds.indexOf(categoryId), 0, categoryNode);
}

/*!
    \internal
*/
int QDeclarativeSupportedCategoriesModel::rowToAddChild(PlaceCategoryNode *node, const QPlaceCategory &category)
{
    Q_ASSERT(node);
    for (int i = 0; i < node->childIds.count(); ++i) {
        if (category.name() < m_categoriesTree.value(node->childIds.at(i))->declCategory->name())
            return i;
    }
    return node->childIds.count();
}

/*!
    \qmlsignal CategoryModel::dataChanged()

   This signal is emitted when significant changes have been made to the underlying datastore.

   Applications should act on this signal at their own discretion.  The data
   provided by the model could be out of date and so the model should be reupdated
   sometime, however an immediate reupdate may be disconcerting to users if the categories
   change without any action on their part.

   The corresponding handler is \c onDataChanged.
*/

QT_END_NAMESPACE
