/****************************************************************************
**
** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module 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 "qabstractaspect.h"
#include "qabstractaspect_p.h"

#include <QMetaObject>
#include <QMetaProperty>

#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertyvalueaddedchange.h>
#include <Qt3DCore/qpropertyvalueremovedchange.h>
#include <Qt3DCore/qcomponentaddedchange.h>
#include <Qt3DCore/qcomponentremovedchange.h>

#include <Qt3DCore/private/corelogging_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnode_p.h>

QT_BEGIN_NAMESPACE

namespace Qt3DCore {

QAbstractAspectPrivate::QAbstractAspectPrivate()
    : QObjectPrivate()
    , m_root(nullptr)
    , m_rootId()
    , m_aspectManager(nullptr)
    , m_jobManager(nullptr)
    , m_arbiter(nullptr)
{
}

QAbstractAspectPrivate::~QAbstractAspectPrivate()
{
}

QAbstractAspectPrivate *QAbstractAspectPrivate::get(QAbstractAspect *aspect)
{
    return aspect->d_func();
}

/*!
 * \internal
 * Called in the context of the main thread
 */
void QAbstractAspectPrivate::onEngineAboutToShutdown()
{
}

/*! \internal */
void QAbstractAspectPrivate::registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing)
{
    const auto f = supportsSyncing ? QAbstractAspectPrivate::SupportsSyncing : QAbstractAspectPrivate::DefaultMapper;
    m_backendCreatorFunctors.insert(&obj, {functor, f});
}

/*! \internal */
void QAbstractAspectPrivate::unregisterBackendType(const QMetaObject &mo)
{
    m_backendCreatorFunctors.remove(&mo);
}

/*!
 * \class Qt3DCore::QAbstractAspect
 * \inheaderfile Qt3DCore/QAbstractAspect
 * \inherits QObject
 * \inmodule Qt3DCore
 * \brief QAbstractAspect is the base class for aspects that provide a vertical slice of behavior.
 */

/*!
 * \fn void Qt3DCore::QAbstractAspect::registerBackendType(const Qt3DCore::QBackendNodeMapperPtr &functor)
 * Registers backend with \a functor.
 */

/*!
 * \macro QT3D_REGISTER_ASPECT(name, AspectType)
 * \relates Qt3DCore::QAbstractAspect
 *
 * Convenience macro for registering \a AspectType for instantiation by the
 * currently set Qt3DCore::QAspectFactory. This makes it possible to create an
 * instance of \a AspectType in the aspect thread by later passing \a name to
 * Qt3DCore::QAspectEngine::registerAspect(const QString &name).
 *
 * \note It is also possible to register a new aspect without using this macro
 * by instead using Qt3DCore::QAspectEngine::registerAspect(QAbstractAspect *aspect)
 * which will handle moving a previously created aspect instance to the aspect
 * thread context.
 *
 * KDAB has published a few articles about writing custom Qt3D aspects
 * \l {https://www.kdab.com/writing-custom-qt-3d-aspect/}{on their blog}. These
 * provide an excellent starting point if you wish to learn more about it.
 */


/*!
 * Constructs a new QAbstractAspect with \a parent
 */
QAbstractAspect::QAbstractAspect(QObject *parent)
    : QAbstractAspect(*new QAbstractAspectPrivate, parent) {}

/*!
 * \typedef Qt3DCore::QAspectJobPtr
 * \relates Qt3DCore::QAbstractAspect
 *
 * A shared pointer for QAspectJob.
 */

/*!
 * \typedef Qt3DCore::QBackendNodeMapperPtr
 * \relates Qt3DCore::QAbstractAspect
 *
 * A shared pointer for QBackendNodeMapper.
 */

/*!
 * \internal
 */
QAbstractAspect::QAbstractAspect(QAbstractAspectPrivate &dd, QObject *parent)
    : QObject(dd, parent)
{
}

/*!
    \internal
*/
QAbstractAspect::~QAbstractAspect()
{
}

/*!
 * \return root entity node id.
 */
QNodeId QAbstractAspect::rootEntityId() const Q_DECL_NOEXCEPT
{
    Q_D(const QAbstractAspect);
    return d->m_rootId;
}

/*!
 * Registers backend with \a obj and \a functor.
 */
void QAbstractAspect::registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor)
{
    Q_D(QAbstractAspect);
    d->m_backendCreatorFunctors.insert(&obj, {functor, QAbstractAspectPrivate::DefaultMapper});
}

void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
{
    Q_D(QAbstractAspect);
    d->m_backendCreatorFunctors.remove(&obj);
}

QVariant QAbstractAspect::executeCommand(const QStringList &args)
{
    Q_UNUSED(args)
    return QVariant();
}

QVector<QAspectJobPtr> QAbstractAspect::jobsToExecute(qint64 time)
{
    Q_UNUSED(time)
    return QVector<QAspectJobPtr>();
}

QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(const QMetaObject *metaObj) const
{
    Q_ASSERT(metaObj);
    BackendNodeMapperAndInfo info;

    while (metaObj != nullptr && info.first.isNull()) {
        info = m_backendCreatorFunctors.value(metaObj);
        metaObj = metaObj->superClass();
    }
    return info;
}

void QAbstractAspectPrivate::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes)
{
    for (auto node: qAsConst(nodes)) {
        const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo;
        const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
        const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;

        if (!backendNodeMapper)
            continue;

        QBackendNode *backend = backendNodeMapper->get(node->id());
        if (!backend)
            continue;

        const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;
        if (supportsSyncing)
            syncDirtyFrontEndNode(node, backend, false);
        else
            sendPropertyMessages(node, backend);
    }
}

void QAbstractAspectPrivate::syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes)
{
    for (const auto &nodeChange: qAsConst(nodes)) {
        auto getBackend = [this](QNode *node) -> std::tuple<QBackendNode *, bool> {
            const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo;
            const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
            const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;

            if (!backendNodeMapper)
                return {};

            QBackendNode *backend = backendNodeMapper->get(node->id());
            if (!backend)
                return {};

            const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;

            return std::tuple<QBackendNode *, bool>(backend, supportsSyncing);
        };

        auto nodeInfo = getBackend(nodeChange.node);
        if (!std::get<0>(nodeInfo))
            continue;

        auto subNodeInfo = getBackend(nodeChange.subNode);
        if (!std::get<0>(subNodeInfo))
            continue;

        switch (nodeChange.change) {
        case PropertyValueAdded: {
            if (std::get<1>(nodeInfo))
                break; // do nothing as the node will be dirty anyway

            QPropertyValueAddedChange change(nodeChange.node->id());
            change.setPropertyName(nodeChange.property);
            change.setAddedValue(QVariant::fromValue(nodeChange.subNode->id()));
            QPropertyValueAddedChangePtr pChange(&change, [](QPropertyValueAddedChange *) { });
            std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
        }
        break;
        case PropertyValueRemoved: {
            if (std::get<1>(nodeInfo))
                break; // do nothing as the node will be dirty anyway

            QPropertyValueRemovedChange change(nodeChange.node->id());
            change.setPropertyName(nodeChange.property);
            change.setRemovedValue(QVariant::fromValue(nodeChange.subNode->id()));
            QPropertyValueRemovedChangePtr pChange(&change, [](QPropertyValueRemovedChange *) { });
            std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
        }
        break;
        case ComponentAdded: {
            // let the entity know it has a new component
            if (std::get<1>(nodeInfo)) {
                QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentAdded(nodeChange.subNode);
            } else {
                QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
                QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { });
                std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
            }

            // let the component know it was added to an entity
            if (std::get<1>(subNodeInfo)) {
                QBackendNodePrivate::get(std::get<0>(subNodeInfo))->addedToEntity(nodeChange.node);
            } else {
                QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
                QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { });
                std::get<0>(subNodeInfo)->sceneChangeEvent(pChange);
            }
        }
        break;
        case ComponentRemoved: {
            // let the entity know a component was removed
            if (std::get<1>(nodeInfo)) {
                QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentRemoved(nodeChange.subNode);
            } else {
                QComponentRemovedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
                QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { });
                std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
            }

            // let the component know it was removed from an entity
            if (std::get<1>(subNodeInfo)) {
                QBackendNodePrivate::get(std::get<0>(subNodeInfo))->removedFromEntity(nodeChange.node);
            } else {
                QComponentRemovedChange change(qobject_cast<Qt3DCore::QEntity *>(nodeChange.node), qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode));
                QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { });
                std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
            }
        }
        break;
        default:
            break;
        }
    }
}

void QAbstractAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
{
    Q_ASSERT(false); // overload in derived class
    if (!firstTime)
        sendPropertyMessages(node, backend);
}

void QAbstractAspectPrivate::sendPropertyMessages(QNode *node, QBackendNode *backend) const
{
    const int offset = QNode::staticMetaObject.propertyOffset();
    const auto metaObj = node->metaObject();
    const int count = metaObj->propertyCount();

    const auto toBackendValue = [](const QVariant &data) -> QVariant
    {
        if (data.canConvert<QNode*>()) {
            QNode *node = data.value<QNode*>();

            // Ensure the node and all ancestors have issued their node creation changes.
            // We can end up here if a newly created node with a parent is immediately set
            // as a property on another node. In this case the deferred call to
            // _q_postConstructorInit() will not have happened yet as the event
            // loop will still be blocked. We need to do this for all ancestors,
            // since the subtree of this node otherwise can end up on the backend
            // with a reference to a non-existent parent.
            if (node)
                QNodePrivate::get(node)->_q_ensureBackendNodeCreated();

            const QNodeId id = node ? node->id() : QNodeId();
            return QVariant::fromValue(id);
        }

        return data;
    };

    QPropertyUpdatedChange change(node->id());
    QPropertyUpdatedChangePtr pchange(&change, [](QPropertyUpdatedChange *) { });
    for (int index = offset; index < count; index++) {
        const QMetaProperty pro = metaObj->property(index);
        change.setPropertyName(pro.name());
        change.setValue(toBackendValue(pro.read(node)));
        backend->sceneChangeEvent(pchange);
    }

    auto const dynamicProperties = node->dynamicPropertyNames();
    for (const QByteArray &name: dynamicProperties) {
        change.setPropertyName(name.data());
        change.setValue(toBackendValue(node->property(name.data())));
        backend->sceneChangeEvent(pchange);
    }
}

QBackendNode *QAbstractAspectPrivate::createBackendNode(const NodeTreeChange &change) const
{
    const QMetaObject *metaObj = change.metaObj;
    const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
    const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;

    if (!backendNodeMapper)
        return nullptr;

    QBackendNode *backend = backendNodeMapper->get(change.id);
    if (backend != nullptr)
        return backend;

    QNode *node = change.node;
    QNodeCreatedChangeBasePtr creationChange;
    const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;
    if (supportsSyncing) {
        // All objects modified to use syncing should only use the id in the creation functor
        QNodeCreatedChangeBase changeObj(node);
        creationChange = QNodeCreatedChangeBasePtr(&changeObj, [](QNodeCreatedChangeBase *) {});
        backend = backendNodeMapper->create(creationChange);
    } else {
        creationChange = node->createNodeCreationChange();
        backend = backendNodeMapper->create(creationChange);
    }

    if (!backend)
        return nullptr;

    // TODO: Find some place else to do all of this function from the arbiter
    backend->setPeerId(change.id);

    // Backend could be null if the user decides that his functor should only
    // perform some action when encountering a given type of item but doesn't need to
    // return a QBackendNode pointer.

    QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend);
    backendPriv->setEnabled(node->isEnabled());

    // TO DO: Find a way to specify the changes to observe
    // Register backendNode with QChangeArbiter
    if (m_arbiter != nullptr) { // Unit tests may not have the arbiter registered
        qCDebug(Nodes) << q_func()->objectName() << "Creating backend node for node id"
                       << node->id() << "of type" << QNodePrivate::get(node)->m_typeInfo->className();
        m_arbiter->registerObserver(backendPriv, backend->peerId(), AllChanges);
        if (backend->mode() == QBackendNode::ReadWrite)
            m_arbiter->scene()->addObservable(backendPriv, backend->peerId());
    }

    if (supportsSyncing)
        syncDirtyFrontEndNode(node, backend, true);
    else
        backend->initializeFromPeer(creationChange);

    return backend;
}

void QAbstractAspectPrivate::clearBackendNode(const NodeTreeChange &change) const
{
    const QMetaObject *metaObj = change.metaObj;
    const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
    const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;

    if (!backendNodeMapper)
        return;

    // Request the mapper to destroy the corresponding backend node
    QBackendNode *backend = backendNodeMapper->get(change.id);
    if (backend) {
        qCDebug(Nodes) << "Deleting backend node for node id"
                       << change.id << "of type" << metaObj->className();
        QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend);
        m_arbiter->unregisterObserver(backendPriv, backend->peerId());
        if (backend->mode() == QBackendNode::ReadWrite)
            m_arbiter->scene()->removeObservable(backendPriv, backend->peerId());
        backendNodeMapper->destroy(change.id);
    }
}

void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QVector<NodeTreeChange> &nodesChanges)
{
    qCDebug(Aspects) << Q_FUNC_INFO << "rootObject =" << rootObject;
    if (rootObject == m_root)
        return;

    m_root = rootObject;
    m_rootId = rootObject->id();

    for (const NodeTreeChange &change : nodesChanges)
        createBackendNode(change);
}


QServiceLocator *QAbstractAspectPrivate::services() const
{
    return m_aspectManager ? m_aspectManager->serviceLocator() : nullptr;
}

QAbstractAspectJobManager *QAbstractAspectPrivate::jobManager() const
{
    return m_jobManager;
}

QVector<QAspectJobPtr> QAbstractAspectPrivate::jobsToExecute(qint64 time)
{
    Q_Q(QAbstractAspect);
    auto res = q->jobsToExecute(time);

    {
        QMutexLocker lock(&m_singleShotMutex);
        res << m_singleShotJobs;
        m_singleShotJobs.clear();
    }

    return res;
}

void QAbstractAspectPrivate::jobsDone()
{

}

/*!
 * Called in the context of the aspect thread once the aspect has been registered.
 * This provides an opportunity for the aspect to do any initialization tasks that
 * require to be in the aspect thread context such as creating QObject subclasses that
 * must have affinity with this thread.
 *
 * \sa onUnregistered
 */
void QAbstractAspect::onRegistered()
{
}

/*!
 * Called in the context of the aspect thread during unregistration
 * of the aspect. This gives the aspect a chance to do any final pieces of
 * cleanup that it would not do when just changing to a new scene.
 *
 * \sa onRegistered
 */
void QAbstractAspect::onUnregistered()
{
}

/*!
 *
 * Called in the QAspectThread context
 */
void QAbstractAspect::onEngineStartup()
{
}

/*!
 *
 * Called in the QAspectThread context
 */
void QAbstractAspect::onEngineShutdown()
{
}

void QAbstractAspect::scheduleSingleShotJob(const Qt3DCore::QAspectJobPtr &job)
{
    Q_D(QAbstractAspect);
    QMutexLocker lock(&d->m_singleShotMutex);
    d->m_singleShotJobs.push_back(job);
}

namespace Debug {

AsynchronousCommandReply::AsynchronousCommandReply(const QString &commandName, QObject *parent)
    : QObject(parent)
    , m_commandName(commandName)
    , m_finished(false)
{
}

void AsynchronousCommandReply::setFinished(bool replyFinished)
{
    m_finished = replyFinished;
    if (m_finished)
        emit finished(this);
}

void AsynchronousCommandReply::setData(const QByteArray &data)
{
    m_data = data;
}

} // Debug


} // of namespace Qt3DCore

QT_END_NAMESPACE
