/****************************************************************************
**
** Copyright (C) 2017 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects 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 "qremoteobjectsource.h"
#include "qremoteobjectsource_p.h"
#include "qremoteobjectnode.h"
#include "qremoteobjectdynamicreplica.h"

#include "qconnectionfactories_p.h"
#include "qremoteobjectsourceio_p.h"
#include "qremoteobjectabstractitemmodeladapter_p.h"

#include <QtCore/qmetaobject.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractitemmodel.h>

#include <algorithm>
#include <iterator>

QT_BEGIN_NAMESPACE

using namespace QRemoteObjectPackets;
using namespace QRemoteObjectStringLiterals;

const int QRemoteObjectSourceBase::qobjectPropertyOffset = QObject::staticMetaObject.propertyCount();
const int QRemoteObjectSourceBase::qobjectMethodOffset = QObject::staticMetaObject.methodCount();
static const QByteArray s_classinfoRemoteobjectSignature(QCLASSINFO_REMOTEOBJECT_SIGNATURE);

QByteArray QtPrivate::qtro_classinfo_signature(const QMetaObject *metaObject)
{
    if (!metaObject)
        return QByteArray{};

    for (int i = metaObject->classInfoOffset(); i < metaObject->classInfoCount(); ++i) {
        auto ci = metaObject->classInfo(i);
        if (s_classinfoRemoteobjectSignature == ci.name())
            return ci.value();
    }
    return QByteArray{};
}

inline bool qtro_is_cloned_method(const QMetaObject *mobj, int local_method_index)
{
    const auto priv = reinterpret_cast<const QtPrivate::QMetaObjectPrivate*>(mobj->d.data);
    Q_ASSERT(local_method_index < priv->methodCount);
    int handle = priv->methodData + 5 * local_method_index;
    if (mobj->d.data[handle + 4] & 0x20 /*MethodFlags::MethodCloned*/)
        return true;
    return false;
}

QRemoteObjectSourceBase::QRemoteObjectSourceBase(QObject *obj, Private *d, const SourceApiMap *api,
                                                 QObject *adapter)
    : QObject(obj),
      m_object(obj),
      m_adapter(adapter),
      m_api(api),
      d(d)
{
    if (!obj) {
        qCWarning(QT_REMOTEOBJECT) << "QRemoteObjectSourceBase: Cannot replicate a NULL object" << m_api->name();
        return;
    }

    setConnections();

    const int nChildren = api->m_models.count() + api->m_subclasses.count();
    if (nChildren > 0) {
        QVector<int> roles;
        const int numProperties = api->propertyCount();
        int modelIndex = 0, subclassIndex = 0;
        for (int i = 0; i < numProperties; ++i) {
            if (api->isAdapterProperty(i))
                continue;
            const int index = api->sourcePropertyIndex(i);
            const auto property = m_object->metaObject()->property(index);
            if (QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject)) {
                auto propertyMeta = QMetaType::metaObjectForType(property.userType());
                QObject *child = property.read(m_object).value<QObject *>();
                if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) {
                    const auto modelInfo = api->m_models.at(modelIndex++);
                    QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(child);
                    QAbstractItemAdapterSourceAPI<QAbstractItemModel, QAbstractItemModelSourceAdapter> *modelApi =
                        new QAbstractItemAdapterSourceAPI<QAbstractItemModel, QAbstractItemModelSourceAdapter>(modelInfo.name);
                    if (!model)
                        m_children.insert(i, new QRemoteObjectSource(nullptr, d, modelApi, nullptr));
                    else {
                        roles.clear();
                        const auto knownRoles = model->roleNames();
                        for (auto role : modelInfo.roles.split('|')) {
                            if (role.isEmpty())
                                continue;
                            const int roleIndex = knownRoles.key(role, -1);
                            if (roleIndex == -1) {
                                qCWarning(QT_REMOTEOBJECT) << "Invalid role" << role << "for model" << model->metaObject()->className();
                                qCWarning(QT_REMOTEOBJECT) << "  known roles:" << knownRoles;
                            } else
                                roles << roleIndex;
                        }
                        auto adapter = new QAbstractItemModelSourceAdapter(model, nullptr,
                                                                           roles.isEmpty() ? knownRoles.keys().toVector() : roles);
                        m_children.insert(i, new QRemoteObjectSource(model, d, modelApi, adapter));
                    }
                } else {
                    const auto classApi = api->m_subclasses.at(subclassIndex++);
                    m_children.insert(i, new QRemoteObjectSource(child, d, classApi, nullptr));
                }
            }
        }
    }
}

QRemoteObjectSource::QRemoteObjectSource(QObject *obj, Private *d, const SourceApiMap *api, QObject *adapter)
    : QRemoteObjectSourceBase(obj, d, api, adapter)
    , m_name(api->typeName() == QLatin1String("QAbstractItemModelAdapter") ? MODEL().arg(api->name()) : CLASS().arg(api->name()))
{
    if (obj)
        d->m_sourceIo->registerSource(this);
}

QRemoteObjectRootSource::QRemoteObjectRootSource(QObject *obj, const SourceApiMap *api,
                                                 QObject *adapter, QRemoteObjectSourceIo *sourceIo)
    : QRemoteObjectSourceBase(obj, new Private(sourceIo, this), api, adapter)
    , m_name(api->name())
{
    d->m_sourceIo->registerSource(this);
}

QRemoteObjectSourceBase::~QRemoteObjectSourceBase()
{
    delete m_api;
}

void QRemoteObjectSourceBase::setConnections()
{
    const QMetaObject *meta = m_object->metaObject();

    const int index = meta->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE);
    if (index != -1) { //We have an object created from repc or at least with QCLASSINFO defined
        while (true) {
            Q_ASSERT(meta->superClass()); //This recurses to QObject, which doesn't have QCLASSINFO_REMOTEOBJECT_TYPE
            if (index != meta->superClass()->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE)) //At the point we don't find the same QCLASSINFO_REMOTEOBJECT_TYPE,
                            //we have the metaobject we should work from
                break;
            meta = meta->superClass();
        }
    }

    for (int idx = 0; idx < m_api->signalCount(); ++idx) {
        const int sourceIndex = m_api->sourceSignalIndex(idx);
        const bool isAdapter = m_api->isAdapterSignal(idx);
        const auto targetMeta = isAdapter ? m_adapter->metaObject() : meta;

        // don't connect cloned signals, or we end up with multiple emissions
        if (qtro_is_cloned_method(targetMeta, sourceIndex - targetMeta->methodOffset()))
            continue;

        // This basically connects the parent Signals (note, all dynamic properties have onChange
        //notifications, thus signals) to us.  Normally each Signal is mapped to a unique index,
        //but since we are forwarding them all, we keep the offset constant.
        //
        //We know no one will inherit from this class, so no need to worry about indices from
        //derived classes.
        const auto target = isAdapter ? m_adapter : m_object;
        if (!QMetaObject::connect(target, sourceIndex, this, QRemoteObjectSource::qobjectMethodOffset+idx, Qt::DirectConnection, 0)) {
            qCWarning(QT_REMOTEOBJECT) << "QRemoteObjectSourceBase: QMetaObject::connect returned false. Unable to connect.";
            return;
        }

        qCDebug(QT_REMOTEOBJECT) << "Connection made" << idx << sourceIndex
                                 << targetMeta->method(sourceIndex).name();
    }
}

void QRemoteObjectSourceBase::resetObject(QObject *newObject)
{
    if (m_object)
        m_object->disconnect(this);
    if (m_adapter) {
        m_adapter->disconnect(this);
        delete m_adapter;
        m_adapter = nullptr;
    }
    // We need some dynamic replica specific code here, in case an object had null sub-classes that
    // have been replaced with real objects.  In this case, the ApiMap could be wrong and need updating.
    if (newObject && qobject_cast<QRemoteObjectDynamicReplica *>(newObject) && m_api->isDynamic()) {
        auto api = static_cast<const DynamicApiMap*>(m_api);
        if (api->m_properties[0] == 0) { // 0 is an index into QObject itself, so this isn't a valid QtRO index
            const auto rep = qobject_cast<QRemoteObjectDynamicReplica *>(newObject);
            auto tmp = m_api;
            m_api = new DynamicApiMap(newObject, rep->metaObject(), api->m_name, QLatin1String(rep->metaObject()->className()));
            qCDebug(QT_REMOTEOBJECT) << "  Reset m_api for" << api->m_name << "using new metaObject:" << rep->metaObject()->className();
            delete tmp;
        }
    }

    m_object = newObject;
    auto model = qobject_cast<QAbstractItemModel *>(newObject);
    if (model) {
        d->m_sourceIo->registerSource(this);
        m_adapter = new QAbstractItemModelSourceAdapter(model, nullptr, model->roleNames().keys().toVector());
    }

    setParent(newObject);
    if (newObject)
        setConnections();

    const int nChildren = m_api->m_models.count() + m_api->m_subclasses.count();
    if (nChildren == 0)
        return;

    if (!newObject) {
        for (auto child : m_children)
            child->resetObject(nullptr);
        return;
    }

    for (int i : m_children.keys()) {
        const int index = m_api->sourcePropertyIndex(i);
        const auto property = m_object->metaObject()->property(index);
        QObject *child = property.read(m_object).value<QObject *>();
        m_children[i]->resetObject(child);
    }
}

QRemoteObjectSource::~QRemoteObjectSource()
{
    for (auto it : m_children) {
        // We used QPointers for m_children because we don't control the lifetime of child QObjects
        // Since the this/source QObject's parent is the referenced QObject, it could have already
        // been deleted
        delete it;
    }
}

QRemoteObjectRootSource::~QRemoteObjectRootSource()
{
    for (auto it : m_children) {
        // We used QPointers for m_children because we don't control the lifetime of child QObjects
        // Since the this/source QObject's parent is the referenced QObject, it could have already
        // been deleted
        delete it;
    }
    d->m_sourceIo->unregisterSource(this);
    // removeListener tries to modify d->m_listeners, this is O(N²),
    // so clear d->m_listeners prior to calling unregister (consume loop).
    // We can do this, because we don't care about the return value of removeListener() here.
    for (IoDeviceBase *io : qExchange(d->m_listeners, {})) {
        removeListener(io, true);
    }
    delete d;
}

QVariantList* QRemoteObjectSourceBase::marshalArgs(int index, void **a)
{
    QVariantList &list = m_marshalledArgs;
    int N = m_api->signalParameterCount(index);
    if (N == 1 && QMetaType::typeFlags(m_api->signalParameterType(index, 0)).testFlag(QMetaType::PointerToQObject))
        N = 0; // Don't try to send pointers, the will be handle by QRO_
    if (list.size() < N)
        list.reserve(N);
    const int minFill = std::min(list.size(), N);
    for (int i = 0; i < minFill; ++i) {
        const int type = m_api->signalParameterType(index, i);
        if (type == QMetaType::QVariant)
            list[i] = *reinterpret_cast<QVariant *>(a[i + 1]);
        else
            list[i] = QVariant(type, a[i + 1]);
    }
    for (int i = list.size(); i < N; ++i) {
        const int type = m_api->signalParameterType(index, i);
        if (type == QMetaType::QVariant)
            list << *reinterpret_cast<QVariant *>(a[i + 1]);
        else
            list << QVariant(type, a[i + 1]);
    }
    for (int i = N; i < list.size(); ++i)
        list.removeLast();
    return &m_marshalledArgs;
}

bool QRemoteObjectSourceBase::invoke(QMetaObject::Call c, int index, const QVariantList &args, QVariant* returnValue)
{
    int status = -1;
    int flags = 0;
    bool forAdapter = (c == QMetaObject::InvokeMetaMethod ? m_api->isAdapterMethod(index) : m_api->isAdapterProperty(index));
    int resolvedIndex = (c == QMetaObject::InvokeMetaMethod ? m_api->sourceMethodIndex(index) : m_api->sourcePropertyIndex(index));
    if (resolvedIndex < 0)
        return false;
    QVarLengthArray<void*, 10> param(args.size() + 1);

    if (c == QMetaObject::InvokeMetaMethod) {
        QMetaMethod method;
        if (!forAdapter)
            method = parent()->metaObject()->method(resolvedIndex);

        if (returnValue) {
            if (!forAdapter && method.isValid() && method.returnType() == QMetaType::QVariant)
                param[0] = const_cast<void*>(reinterpret_cast<const void*>(returnValue));
            else
                param[0] = returnValue->data();
        } else {
            param[0] = nullptr;
        }

        auto argument = [&](int i) -> void * {
            if ((forAdapter && m_api->methodParameterType(index, i) == QMetaType::QVariant) ||
                    (method.isValid() && method.parameterType(i) == QMetaType::QVariant)) {
                return const_cast<void*>(reinterpret_cast<const void*>(&args.at(i)));
            }
            return const_cast<void*>(args.at(i).data());
        };

        for (int i = 0; i < args.size(); ++i) {
            param[i + 1] = argument(i);
        }
    } else if (c == QMetaObject::WriteProperty || c == QMetaObject::ReadProperty) {
        bool isQVariant = !forAdapter && parent()->metaObject()->property(resolvedIndex).userType() == QMetaType::QVariant;
        for (int i = 0; i < args.size(); ++i) {
            if (isQVariant)
                param[i] = const_cast<void*>(reinterpret_cast<const void*>(&args.at(i)));
            else
                param[i] = const_cast<void*>(args.at(i).data());
        }
        if (c == QMetaObject::WriteProperty) {
            Q_ASSERT(param.size() == 2); // for return-value and setter value
            // check QMetaProperty::write for an explanation of these
            param.append(&status);
            param.append(&flags);
        }
    } else {
        // Better safe than sorry
        return false;
    }
    int r = -1;
    if (forAdapter)
        r = m_adapter->qt_metacall(c, resolvedIndex, param.data());
    else
        r = parent()->qt_metacall(c, resolvedIndex, param.data());
    return r == -1 && status == -1;
}

void QRemoteObjectSourceBase::handleMetaCall(int index, QMetaObject::Call call, void **a)
{
    if (d->m_listeners.empty())
        return;

    int propertyIndex = m_api->propertyIndexFromSignal(index);
    if (propertyIndex >= 0) {
        const int internalIndex = m_api->propertyRawIndexFromSignal(index);
        const auto target = m_api->isAdapterProperty(internalIndex) ? m_adapter : m_object;
        const QMetaProperty mp = target->metaObject()->property(propertyIndex);
        qCDebug(QT_REMOTEOBJECT) << "Sending Invoke Property" << (m_api->isAdapterSignal(internalIndex) ? "via adapter" : "") << internalIndex << propertyIndex << mp.name() << mp.read(target);

        serializePropertyChangePacket(this, index);
        d->m_packet.baseAddress = d->m_packet.size;
        propertyIndex = internalIndex;
    }

    qCDebug(QT_REMOTEOBJECT) << "# Listeners" << d->m_listeners.length();
    qCDebug(QT_REMOTEOBJECT) << "Invoke args:" << m_object
                             << (call == 0 ? QLatin1String("InvokeMetaMethod") : QStringLiteral("Non-invoked call: %d").arg(call))
                             << m_api->signalSignature(index) << *marshalArgs(index, a);

    serializeInvokePacket(d->m_packet, name(), call, index, *marshalArgs(index, a), -1, propertyIndex);
    d->m_packet.baseAddress = 0;

    for (IoDeviceBase *io : qAsConst(d->m_listeners))
        io->write(d->m_packet.array, d->m_packet.size);
}

void QRemoteObjectRootSource::addListener(IoDeviceBase *io, bool dynamic)
{
    d->m_listeners.append(io);
    d->isDynamic = d->isDynamic || dynamic;

    if (dynamic) {
        d->sentTypes.clear();
        serializeInitDynamicPacket(d->m_packet, this);
        io->write(d->m_packet.array, d->m_packet.size);
    } else {
        serializeInitPacket(d->m_packet, this);
        io->write(d->m_packet.array, d->m_packet.size);
    }
}

int QRemoteObjectRootSource::removeListener(IoDeviceBase *io, bool shouldSendRemove)
{
    d->m_listeners.removeAll(io);
    if (shouldSendRemove)
    {
        serializeRemoveObjectPacket(d->m_packet, m_api->name());
        io->write(d->m_packet.array, d->m_packet.size);
    }
    return d->m_listeners.length();
}

int QRemoteObjectSourceBase::qt_metacall(QMetaObject::Call call, int methodId, void **a)
{
    methodId = QObject::qt_metacall(call, methodId, a);
    if (methodId < 0)
        return methodId;

    if (call == QMetaObject::InvokeMetaMethod)
        handleMetaCall(methodId, call, a);

    return -1;
}

DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, const QString &name, const QString &typeName)
    : m_name(name),
      m_typeName(typeName),
      m_metaObject(metaObject),
      m_cachedMetamethodIndex(-1)
{
    m_enumOffset = metaObject->enumeratorOffset();
    m_enumCount = metaObject->enumeratorCount() - m_enumOffset;

    const int propCount = metaObject->propertyCount();
    const int propOffset = metaObject->propertyOffset();
    m_properties.reserve(propCount-propOffset);
    int i = 0;
    for (i = propOffset; i < propCount; ++i) {
        const QMetaProperty property = metaObject->property(i);
        if (QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject)) {
            auto propertyMeta = QMetaType::metaObjectForType(property.userType());
            QObject *child = property.read(object).value<QObject *>();
            if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) {
                const QByteArray name = QByteArray::fromRawData(property.name(),
                                                                qstrlen(property.name()));
                const QByteArray infoName = name.toUpper() + QByteArrayLiteral("_ROLES");
                const int infoIndex = metaObject->indexOfClassInfo(infoName.constData());
                QByteArray roleInfo;
                if (infoIndex >= 0) {
                    auto ci = metaObject->classInfo(infoIndex);
                    roleInfo = QByteArray::fromRawData(ci.value(), qstrlen(ci.value()));
                }
                m_models << ModelInfo({qobject_cast<QAbstractItemModel *>(child),
                                       QString::fromLatin1(property.name()),
                                       roleInfo});
            } else {
                const QMetaObject *meta = child ? child->metaObject() : propertyMeta;
                QString typeName = QtRemoteObjects::getTypeNameAndMetaobjectFromClassInfo(meta);
                if (typeName.isNull()) {
                    typeName = QString::fromLatin1(propertyMeta->className());
                    // TODO better way to ensure we have consistent typenames between source/replicas?
                    if (typeName.endsWith(QLatin1String("Source")))
                        typeName.chop(6);
                }

                m_subclasses << new DynamicApiMap(child, meta, QString::fromLatin1(property.name()), typeName);
            }
        }
        m_properties << i;
        const int notifyIndex = metaObject->property(i).notifySignalIndex();
        if (notifyIndex != -1) {
            m_signals << notifyIndex;
            m_propertyAssociatedWithSignal.append(i-propOffset);
            //The starting values of _signals will be the notify signals
            //So if we are processing _signal with index i, api->sourcePropertyIndex(_propertyAssociatedWithSignal.at(i))
            //will be the property that changed.  This is only valid if i < _propertyAssociatedWithSignal.size().
        }
    }
    const int methodCount = metaObject->methodCount();
    const int methodOffset = metaObject->methodOffset();
    for (i = methodOffset; i < methodCount; ++i) {
        const QMetaMethod mm = metaObject->method(i);
        const QMetaMethod::MethodType m = mm.methodType();
        if (m == QMetaMethod::Signal) {
            if (m_signals.indexOf(i) >= 0) //Already added as a property notifier
                continue;
            m_signals << i;
        } else if (m == QMetaMethod::Slot || m == QMetaMethod::Method)
            m_methods << i;
    }

    m_objectSignature = QtPrivate::qtro_classinfo_signature(metaObject);
}

QList<QByteArray> DynamicApiMap::signalParameterNames(int index) const
{
    const int objectIndex = m_signals.at(index);
    checkCache(objectIndex);
    return m_cachedMetamethod.parameterNames();
}

int DynamicApiMap::parameterCount(int objectIndex) const
{
    checkCache(objectIndex);
    return m_cachedMetamethod.parameterCount();
}

int DynamicApiMap::parameterType(int objectIndex, int paramIndex) const
{
    checkCache(objectIndex);
    return m_cachedMetamethod.parameterType(paramIndex);
}

const QByteArray DynamicApiMap::signature(int objectIndex) const
{
    checkCache(objectIndex);
    return m_cachedMetamethod.methodSignature();
}

QMetaMethod::MethodType DynamicApiMap::methodType(int index) const
{
    const int objectIndex = m_methods.at(index);
    checkCache(objectIndex);
    return m_cachedMetamethod.methodType();
}

const QByteArray DynamicApiMap::typeName(int index) const
{
    const int objectIndex = m_methods.at(index);
    checkCache(objectIndex);
    return m_cachedMetamethod.typeName();
}

QList<QByteArray> DynamicApiMap::methodParameterNames(int index) const
{
    const int objectIndex = m_methods.at(index);
    checkCache(objectIndex);
    return m_cachedMetamethod.parameterNames();
}

QT_END_NAMESPACE
