/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
** Copyright (C) 2019 Menlo Systems GmbH, author Arno Rehn <a.rehn@menlosystems.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebChannel 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 "qmetaobjectpublisher_p.h"
#include "qwebchannel.h"
#include "qwebchannel_p.h"
#include "qwebchannelabstracttransport.h"

#include <QEvent>
#include <QJsonDocument>
#include <QDebug>
#include <QJsonObject>
#include <QJsonArray>
#ifndef QT_NO_JSVALUE
#include <QJSValue>
#endif
#include <QUuid>

QT_BEGIN_NAMESPACE

namespace {

// FIXME: QFlags don't have the QMetaType::IsEnumeration flag set, although they have a QMetaEnum entry in the QMetaObject.
// They only way to detect registered QFlags types is to find the named entry in the QMetaObject's enumerator list.
// Ideally, this would be fixed in QMetaType.
bool isQFlagsType(uint id)
{
    QMetaType type(id);

    // Short-circuit to avoid more expensive operations
    QMetaType::TypeFlags flags = type.flags();
    if (flags.testFlag(QMetaType::PointerToQObject) || flags.testFlag(QMetaType::IsEnumeration)
            || flags.testFlag(QMetaType::SharedPointerToQObject) || flags.testFlag(QMetaType::WeakPointerToQObject)
            || flags.testFlag(QMetaType::TrackingPointerToQObject) || flags.testFlag(QMetaType::IsGadget))
    {
        return false;
    }

    const QMetaObject *mo = type.metaObject();
    if (!mo) {
        return false;
    }

    QByteArray name = QMetaType::typeName(id);
    name = name.mid(name.lastIndexOf(":") + 1);
    return mo->indexOfEnumerator(name.constData()) > -1;
}

// Common scores for overload resolution
enum OverloadScore {
    PerfectMatchScore = 0,
    VariantScore = 1,
    NumberBaseScore = 2,
    GenericConversionScore = 100,
    IncompatibleScore = 10000,
};

// Scores the conversion of a double to a number-like user type. Better matches
// for a JS 'number' get a lower score.
int doubleToNumberConversionScore(int userType)
{
    switch (userType) {
    case QMetaType::Bool:
        return NumberBaseScore + 7;
    case QMetaType::Char:
    case QMetaType::SChar:
    case QMetaType::UChar:
        return NumberBaseScore + 6;
    case QMetaType::Short:
    case QMetaType::UShort:
        return NumberBaseScore + 5;
    case QMetaType::Int:
    case QMetaType::UInt:
        return NumberBaseScore + 4;
    case QMetaType::Long:
    case QMetaType::ULong:
        return NumberBaseScore + 3;
    case QMetaType::LongLong:
    case QMetaType::ULongLong:
        return NumberBaseScore + 2;
    case QMetaType::Float:
        return NumberBaseScore + 1;
    case QMetaType::Double:
        return NumberBaseScore;
    default:
        break;
    }

    if (QMetaType::typeFlags(userType) & QMetaType::IsEnumeration)
        return doubleToNumberConversionScore(QMetaType::Int);

    return IncompatibleScore;
}

// Keeps track of the badness of a QMetaMethod candidate for overload resolution
struct OverloadResolutionCandidate
{
    OverloadResolutionCandidate(const QMetaMethod &method = QMetaMethod(), int badness = PerfectMatchScore)
        : method(method), badness(badness)
    {}

    QMetaMethod method;
    int badness;

    bool operator<(const OverloadResolutionCandidate &other) const { return badness < other.badness; }
};

MessageType toType(const QJsonValue &value)
{
    int i = value.toInt(-1);
    if (i >= TYPES_FIRST_VALUE && i <= TYPES_LAST_VALUE) {
        return static_cast<MessageType>(i);
    } else {
        return TypeInvalid;
    }
}

const QString KEY_SIGNALS = QStringLiteral("signals");
const QString KEY_METHODS = QStringLiteral("methods");
const QString KEY_PROPERTIES = QStringLiteral("properties");
const QString KEY_ENUMS = QStringLiteral("enums");
const QString KEY_QOBJECT = QStringLiteral("__QObject*__");
const QString KEY_ID = QStringLiteral("id");
const QString KEY_DATA = QStringLiteral("data");
const QString KEY_OBJECT = QStringLiteral("object");
const QString KEY_DESTROYED = QStringLiteral("destroyed");
const QString KEY_SIGNAL = QStringLiteral("signal");
const QString KEY_TYPE = QStringLiteral("type");
const QString KEY_METHOD = QStringLiteral("method");
const QString KEY_ARGS = QStringLiteral("args");
const QString KEY_PROPERTY = QStringLiteral("property");
const QString KEY_VALUE = QStringLiteral("value");

QJsonObject createResponse(const QJsonValue &id, const QJsonValue &data)
{
    QJsonObject response;
    response[KEY_TYPE] = TypeResponse;
    response[KEY_ID] = id;
    response[KEY_DATA] = data;
    return response;
}

/// TODO: what is the proper value here?
const int PROPERTY_UPDATE_INTERVAL = 50;
}

Q_DECLARE_TYPEINFO(OverloadResolutionCandidate, Q_MOVABLE_TYPE);

QMetaObjectPublisher::QMetaObjectPublisher(QWebChannel *webChannel)
    : QObject(webChannel)
    , webChannel(webChannel)
    , signalHandler(this)
    , clientIsIdle(false)
    , blockUpdates(false)
    , propertyUpdatesInitialized(false)
{
}

QMetaObjectPublisher::~QMetaObjectPublisher()
{

}

void QMetaObjectPublisher::registerObject(const QString &id, QObject *object)
{
    registeredObjects[id] = object;
    registeredObjectIds[object] = id;
    if (propertyUpdatesInitialized) {
        if (!webChannel->d_func()->transports.isEmpty()) {
            qWarning("Registered new object after initialization, existing clients won't be notified!");
            // TODO: send a message to clients that an object was added
        }
        initializePropertyUpdates(object, classInfoForObject(object, Q_NULLPTR));
    }
}

QJsonObject QMetaObjectPublisher::classInfoForObject(const QObject *object, QWebChannelAbstractTransport *transport)
{
    QJsonObject data;
    if (!object) {
        qWarning("null object given to MetaObjectPublisher - bad API usage?");
        return data;
    }

    QJsonArray qtSignals;
    QJsonArray qtMethods;
    QJsonArray qtProperties;
    QJsonObject qtEnums;

    const QMetaObject *metaObject = object->metaObject();
    QSet<int> notifySignals;
    QSet<QString> identifiers;
    for (int i = 0; i < metaObject->propertyCount(); ++i) {
        const QMetaProperty &prop = metaObject->property(i);
        QJsonArray propertyInfo;
        const QString &propertyName = QString::fromLatin1(prop.name());
        propertyInfo.append(i);
        propertyInfo.append(propertyName);
        identifiers << propertyName;
        QJsonArray signalInfo;
        if (prop.hasNotifySignal()) {
            notifySignals << prop.notifySignalIndex();
            // optimize: compress the common propertyChanged notification names, just send a 1
            const QByteArray &notifySignal = prop.notifySignal().name();
            static const QByteArray changedSuffix = QByteArrayLiteral("Changed");
            if (notifySignal.length() == changedSuffix.length() + propertyName.length() &&
                notifySignal.endsWith(changedSuffix) && notifySignal.startsWith(prop.name()))
            {
                signalInfo.append(1);
            } else {
                signalInfo.append(QString::fromLatin1(notifySignal));
            }
            signalInfo.append(prop.notifySignalIndex());
        } else if (!prop.isConstant()) {
            qWarning("Property '%s'' of object '%s' has no notify signal and is not constant, "
                     "value updates in HTML will be broken!",
                     prop.name(), object->metaObject()->className());
        }
        propertyInfo.append(signalInfo);
        propertyInfo.append(wrapResult(prop.read(object), transport));
        qtProperties.append(propertyInfo);
    }
    auto addMethod = [&qtSignals, &qtMethods, &identifiers](int i, const QMetaMethod &method, const QByteArray &rawName) {
        //NOTE: the name must be a string, otherwise it will be converted to '{}' in QML
        const auto name = QString::fromLatin1(rawName);
        // only the first method gets called with its name directly
        // others must be called by explicitly passing the method signature
        if (identifiers.contains(name))
            return;
        identifiers << name;
        // send data as array to client with format: [name, index]
        QJsonArray data;
        data.append(name);
        data.append(i);
        if (method.methodType() == QMetaMethod::Signal) {
            qtSignals.append(data);
        } else if (method.access() == QMetaMethod::Public) {
            qtMethods.append(data);
        }
    };
    for (int i = 0; i < metaObject->methodCount(); ++i) {
        if (notifySignals.contains(i)) {
            continue;
        }
        const QMetaMethod &method = metaObject->method(i);
        addMethod(i, method, method.name());
        // for overload resolution also pass full method signature
        addMethod(i, method, method.methodSignature());
    }
    for (int i = 0; i < metaObject->enumeratorCount(); ++i) {
        QMetaEnum enumerator = metaObject->enumerator(i);
        QJsonObject values;
        for (int k = 0; k < enumerator.keyCount(); ++k) {
            values[QString::fromLatin1(enumerator.key(k))] = enumerator.value(k);
        }
        qtEnums[QString::fromLatin1(enumerator.name())] = values;
    }
    data[KEY_SIGNALS] = qtSignals;
    data[KEY_METHODS] = qtMethods;
    data[KEY_PROPERTIES] = qtProperties;
    if (!qtEnums.isEmpty()) {
        data[KEY_ENUMS] = qtEnums;
    }
    return data;
}

void QMetaObjectPublisher::setClientIsIdle(bool isIdle)
{
    if (clientIsIdle == isIdle) {
        return;
    }
    clientIsIdle = isIdle;
    if (!isIdle && timer.isActive()) {
        timer.stop();
    } else if (isIdle && !timer.isActive()) {
        timer.start(PROPERTY_UPDATE_INTERVAL, this);
    }
}

QJsonObject QMetaObjectPublisher::initializeClient(QWebChannelAbstractTransport *transport)
{
    QJsonObject objectInfos;
    {
        const QHash<QString, QObject *>::const_iterator end = registeredObjects.constEnd();
        for (QHash<QString, QObject *>::const_iterator it = registeredObjects.constBegin(); it != end; ++it) {
            const QJsonObject &info = classInfoForObject(it.value(), transport);
            if (!propertyUpdatesInitialized) {
                initializePropertyUpdates(it.value(), info);
            }
            objectInfos[it.key()] = info;
        }
    }
    propertyUpdatesInitialized = true;
    return objectInfos;
}

void QMetaObjectPublisher::initializePropertyUpdates(const QObject *const object, const QJsonObject &objectInfo)
{
    foreach (const QJsonValue &propertyInfoVar, objectInfo[KEY_PROPERTIES].toArray()) {
        const QJsonArray &propertyInfo = propertyInfoVar.toArray();
        if (propertyInfo.size() < 2) {
            qWarning() << "Invalid property info encountered:" << propertyInfoVar;
            continue;
        }
        const int propertyIndex = propertyInfo.at(0).toInt();
        const QJsonArray &signalData = propertyInfo.at(2).toArray();

        if (signalData.isEmpty()) {
            // Property without NOTIFY signal
            continue;
        }

        const int signalIndex = signalData.at(1).toInt();

        QSet<int> &connectedProperties = signalToPropertyMap[object][signalIndex];

        // Only connect for a property update once
        if (connectedProperties.isEmpty()) {
            signalHandler.connectTo(object, signalIndex);
        }

        connectedProperties.insert(propertyIndex);
    }

    // also always connect to destroyed signal
    signalHandler.connectTo(object, s_destroyedSignalIndex);
}

void QMetaObjectPublisher::sendPendingPropertyUpdates()
{
    if (blockUpdates || !clientIsIdle || pendingPropertyUpdates.isEmpty()) {
        return;
    }

    QJsonArray data;
    QHash<QWebChannelAbstractTransport*, QJsonArray> specificUpdates;

    // convert pending property updates to JSON data
    const PendingPropertyUpdates::const_iterator end = pendingPropertyUpdates.constEnd();
    for (PendingPropertyUpdates::const_iterator it = pendingPropertyUpdates.constBegin(); it != end; ++it) {
        const QObject *object = it.key();
        const QMetaObject *const metaObject = object->metaObject();
        const QString objectId = registeredObjectIds.value(object);
        const SignalToPropertyNameMap &objectsSignalToPropertyMap = signalToPropertyMap.value(object);
        // maps property name to current property value
        QJsonObject properties;
        // maps signal index to list of arguments of the last emit
        QJsonObject sigs;
        const SignalToArgumentsMap::const_iterator sigEnd = it.value().constEnd();
        for (SignalToArgumentsMap::const_iterator sigIt = it.value().constBegin(); sigIt != sigEnd; ++sigIt) {
            // TODO: can we get rid of the int <-> string conversions here?
            foreach (const int propertyIndex, objectsSignalToPropertyMap.value(sigIt.key())) {
                const QMetaProperty &property = metaObject->property(propertyIndex);
                Q_ASSERT(property.isValid());
                properties[QString::number(propertyIndex)] = wrapResult(property.read(object), Q_NULLPTR, objectId);
            }
            sigs[QString::number(sigIt.key())] = QJsonArray::fromVariantList(sigIt.value());
        }
        QJsonObject obj;
        obj[KEY_OBJECT] = objectId;
        obj[KEY_SIGNALS] = sigs;
        obj[KEY_PROPERTIES] = properties;

        // if the object is auto registered, just send the update only to clients which know this object
        if (wrappedObjects.contains(objectId)) {
            foreach (QWebChannelAbstractTransport *transport, wrappedObjects.value(objectId).transports) {
                QJsonArray &arr = specificUpdates[transport];
                arr.push_back(obj);
            }
        } else {
            data.push_back(obj);
        }
    }

    pendingPropertyUpdates.clear();
    QJsonObject message;
    message[KEY_TYPE] = TypePropertyUpdate;

    // data does not contain specific updates
    if (!data.isEmpty()) {
        setClientIsIdle(false);

        message[KEY_DATA] = data;
        broadcastMessage(message);
    }

    // send every property update which is not supposed to be broadcasted
    const QHash<QWebChannelAbstractTransport*, QJsonArray>::const_iterator suend = specificUpdates.constEnd();
    for (QHash<QWebChannelAbstractTransport*, QJsonArray>::const_iterator it = specificUpdates.constBegin(); it != suend; ++it) {
        message[KEY_DATA] = it.value();
        it.key()->sendMessage(message);
    }
}

QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const QMetaMethod &method,
                                              const QJsonArray &args)
{
    if (method.name() == QByteArrayLiteral("deleteLater")) {
        // invoke `deleteLater` on wrapped QObject indirectly
        deleteWrappedObject(object);
        return QJsonValue();
    } else if (!method.isValid()) {
        qWarning() << "Cannot invoke invalid method on object" << object << '.';
        return QJsonValue();
    } else if (method.access() != QMetaMethod::Public) {
        qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
        return QJsonValue();
    } else if (method.methodType() != QMetaMethod::Method && method.methodType() != QMetaMethod::Slot) {
        qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
        return QJsonValue();
    } else if (args.size() > 10) {
        qWarning() << "Cannot invoke method" << method.name() << "on object" << object << "with more than 10 arguments, as that is not supported by QMetaMethod::invoke.";
        return QJsonValue();
    } else if (args.size() > method.parameterCount()) {
        qWarning() << "Ignoring additional arguments while invoking method" << method.name() << "on object" << object << ':'
                   << args.size() << "arguments given, but method only takes" << method.parameterCount() << '.';
    }

    // construct converter objects of QVariant to QGenericArgument
    VariantArgument arguments[10];
    for (int i = 0; i < qMin(args.size(), method.parameterCount()); ++i) {
        arguments[i].value = toVariant(args.at(i), method.parameterType(i));
    }
    // construct QGenericReturnArgument
    QVariant returnValue;
    if (method.returnType() == QMetaType::Void) {
        // Skip return for void methods (prevents runtime warnings inside Qt), and allows
        // QMetaMethod to invoke void-returning methods on QObjects in a different thread.
        method.invoke(object,
                  arguments[0], arguments[1], arguments[2], arguments[3], arguments[4],
                  arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);
    } else {
        // Only init variant with return type if its not a variant itself, which would
        // lead to nested variants which is not what we want.
        if (method.returnType() != QMetaType::QVariant)
            returnValue = QVariant(method.returnType(), 0);

        QGenericReturnArgument returnArgument(method.typeName(), returnValue.data());
        method.invoke(object, returnArgument,
                  arguments[0], arguments[1], arguments[2], arguments[3], arguments[4],
                  arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);
    }
    // now we can call the method
    return returnValue;
}

QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex,
                                            const QJsonArray &args)
{
    const QMetaMethod &method = object->metaObject()->method(methodIndex);
    if (!method.isValid()) {
        qWarning() << "Cannot invoke method of unknown index" << methodIndex << "on object"
                   << object << '.';
        return QJsonValue();
    }
    return invokeMethod(object, method, args);
}

QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const QByteArray &methodName,
                                            const QJsonArray &args)
{
    QVector<OverloadResolutionCandidate> candidates;

    const QMetaObject *mo = object->metaObject();
    for (int i = 0; i < mo->methodCount(); ++i) {
        QMetaMethod method = mo->method(i);
        if (method.name() != methodName || method.parameterCount() != args.count()
                || method.access() != QMetaMethod::Public
                || (method.methodType() != QMetaMethod::Method
                        && method.methodType() != QMetaMethod::Slot)
                || method.parameterCount() > 10)
        {
            // Not a candidate
            continue;
        }

        candidates.append({method, methodOverloadBadness(method, args)});
    }

    if (candidates.isEmpty()) {
        qWarning() << "No candidates found for" << methodName << "with" << args.size()
                   << "arguments on object" << object << '.';
        return QJsonValue();
    }

    std::sort(candidates.begin(), candidates.end());

    if (candidates.size() > 1 && candidates[0].badness == candidates[1].badness) {
        qWarning().nospace() << "Ambiguous overloads for method " << methodName << ". Choosing "
                             << candidates.first().method.methodSignature();
    }

    return invokeMethod(object, candidates.first().method, args);
}

void QMetaObjectPublisher::setProperty(QObject *object, const int propertyIndex, const QJsonValue &value)
{
    QMetaProperty property = object->metaObject()->property(propertyIndex);
    if (!property.isValid()) {
        qWarning() << "Cannot set unknown property" << propertyIndex << "of object" << object;
    } else if (!property.write(object, toVariant(value, property.userType()))) {
        qWarning() << "Could not write value " << value << "to property" << property.name() << "of object" << object;
    }
}

void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments)
{
    if (!webChannel || webChannel->d_func()->transports.isEmpty()) {
        if (signalIndex == s_destroyedSignalIndex)
            objectDestroyed(object);
        return;
    }
    if (!signalToPropertyMap.value(object).contains(signalIndex)) {
        QJsonObject message;
        const QString &objectName = registeredObjectIds.value(object);
        Q_ASSERT(!objectName.isEmpty());
        message[KEY_OBJECT] = objectName;
        message[KEY_SIGNAL] = signalIndex;
        if (!arguments.isEmpty()) {
            message[KEY_ARGS] = wrapList(arguments, Q_NULLPTR, objectName);
        }
        message[KEY_TYPE] = TypeSignal;

        // if the object is wrapped, just send the response to clients which know this object
        if (wrappedObjects.contains(objectName)) {
            foreach (QWebChannelAbstractTransport *transport, wrappedObjects.value(objectName).transports) {
                transport->sendMessage(message);
            }
        } else {
            broadcastMessage(message);
        }

        if (signalIndex == s_destroyedSignalIndex) {
            objectDestroyed(object);
        }
    } else {
        pendingPropertyUpdates[object][signalIndex] = arguments;
        if (clientIsIdle && !blockUpdates && !timer.isActive()) {
            timer.start(PROPERTY_UPDATE_INTERVAL, this);
        }
    }
}

void QMetaObjectPublisher::objectDestroyed(const QObject *object)
{
    const QString &id = registeredObjectIds.take(object);
    Q_ASSERT(!id.isEmpty());
    bool removed = registeredObjects.remove(id)
            || wrappedObjects.remove(id);
    Q_ASSERT(removed);
    Q_UNUSED(removed);

    // only remove from handler when we initialized the property updates
    // cf: https://bugreports.qt.io/browse/QTBUG-60250
    if (propertyUpdatesInitialized) {
        signalHandler.remove(object);
        signalToPropertyMap.remove(object);
    }
    pendingPropertyUpdates.remove(object);
}

QObject *QMetaObjectPublisher::unwrapObject(const QString &objectId) const
{
    if (!objectId.isEmpty()) {
        ObjectInfo objectInfo = wrappedObjects.value(objectId);
        if (objectInfo.object)
            return objectInfo.object;
        QObject *object = registeredObjects.value(objectId);
        if (object)
            return object;
    }

    qWarning() << "No wrapped object" << objectId;
    return Q_NULLPTR;
}

QVariant QMetaObjectPublisher::toVariant(const QJsonValue &value, int targetType) const
{
    if (targetType == QMetaType::QJsonValue) {
        return QVariant::fromValue(value);
    } else if (targetType == QMetaType::QJsonArray) {
        if (!value.isArray())
            qWarning() << "Cannot not convert non-array argument" << value << "to QJsonArray.";
        return QVariant::fromValue(value.toArray());
    } else if (targetType == QMetaType::QJsonObject) {
        if (!value.isObject())
            qWarning() << "Cannot not convert non-object argument" << value << "to QJsonObject.";
        return QVariant::fromValue(value.toObject());
    } else if (QMetaType::typeFlags(targetType) & QMetaType::PointerToQObject) {
        QObject *unwrappedObject = unwrapObject(value.toObject()[KEY_ID].toString());
        if (unwrappedObject == Q_NULLPTR)
            qWarning() << "Cannot not convert non-object argument" << value << "to QObject*.";
        return QVariant::fromValue(unwrappedObject);
    } else if (isQFlagsType(targetType)) {
        int flagsValue = value.toInt();
        return QVariant(targetType, reinterpret_cast<const void*>(&flagsValue));
    }

    // this converts QJsonObjects to QVariantMaps, which is not desired when
    // we want to get a QJsonObject or QJsonValue (see above)
    QVariant variant = value.toVariant();
    if (targetType != QMetaType::QVariant && !variant.convert(targetType)) {
        qWarning() << "Could not convert argument" << value << "to target type" << QVariant::typeToName(targetType) << '.';
    }
    return variant;
}

int QMetaObjectPublisher::conversionScore(const QJsonValue &value, int targetType) const
{
    if (targetType == QMetaType::QJsonValue) {
        return PerfectMatchScore;
    } else if (targetType == QMetaType::QJsonArray) {
        return value.isArray() ? PerfectMatchScore : IncompatibleScore;
    } else if (targetType == QMetaType::QJsonObject) {
        return value.isObject() ? PerfectMatchScore : IncompatibleScore;
    } else if (QMetaType::typeFlags(targetType) & QMetaType::PointerToQObject) {
        if (value.isNull())
            return PerfectMatchScore;
        if (!value.isObject())
            return IncompatibleScore;

        QJsonObject object = value.toObject();
        if (object[KEY_ID].isUndefined())
            return IncompatibleScore;

        QObject *unwrappedObject = unwrapObject(object[KEY_ID].toString());
        return unwrappedObject != Q_NULLPTR ? PerfectMatchScore : IncompatibleScore;
    } else if (targetType == QMetaType::QVariant) {
        return VariantScore;
    }

    // Check if this is a number conversion
    if (value.isDouble()) {
        int score = doubleToNumberConversionScore(targetType);
        if (score != IncompatibleScore) {
            return score;
        }
    }

    QVariant variant = value.toVariant();
    if (variant.userType() == targetType) {
        return PerfectMatchScore;
    } else if (variant.canConvert(targetType)) {
        return GenericConversionScore;
    }

    return IncompatibleScore;
}

int QMetaObjectPublisher::methodOverloadBadness(const QMetaMethod &method, const QJsonArray &args) const
{
    int badness = PerfectMatchScore;
    for (int i = 0; i < args.size(); ++i) {
        badness += conversionScore(args[i], method.parameterType(i));
    }
    return badness;
}

void QMetaObjectPublisher::transportRemoved(QWebChannelAbstractTransport *transport)
{
    auto it = transportedWrappedObjects.find(transport);
    // It is not allowed to modify a container while iterating over it. So save
    // objects which should be removed and call objectDestroyed() on them later.
    QVector<QObject*> objectsForDeletion;
    while (it != transportedWrappedObjects.end() && it.key() == transport) {
        if (wrappedObjects.contains(it.value())) {
            QVector<QWebChannelAbstractTransport*> &transports = wrappedObjects[it.value()].transports;
            transports.removeOne(transport);
            if (transports.isEmpty())
                objectsForDeletion.append(wrappedObjects[it.value()].object);
        }

        it++;
    }

    transportedWrappedObjects.remove(transport);

    foreach (QObject *obj, objectsForDeletion)
        objectDestroyed(obj);
}

// NOTE: transport can be a nullptr
//       in such a case, we need to ensure that the property is registered to
//       the target transports of the parentObjectId
QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelAbstractTransport *transport,
                                            const QString &parentObjectId)
{
    if (QObject *object = result.value<QObject *>()) {
        QString id = registeredObjectIds.value(object);

        QJsonObject classInfo;
        if (id.isEmpty()) {
            // neither registered, nor wrapped, do so now
            id = QUuid::createUuid().toString();
            // store ID before the call to classInfoForObject()
            // in case of self-contained objects it avoids
            // infinite loops
            registeredObjectIds[object] = id;

            classInfo = classInfoForObject(object, transport);

            ObjectInfo oi(object);
            if (transport) {
                oi.transports.append(transport);
                transportedWrappedObjects.insert(transport, id);
            } else {
                // use the transports from the parent object
                oi.transports = wrappedObjects.value(parentObjectId).transports;
                // or fallback to all transports if the parent is not wrapped
                if (oi.transports.isEmpty())
                    oi.transports = webChannel->d_func()->transports;

                for (auto transport : qAsConst(oi.transports)) {
                    transportedWrappedObjects.insert(transport, id);
                }
            }
            wrappedObjects.insert(id, oi);

            initializePropertyUpdates(object, classInfo);
        } else if (wrappedObjects.contains(id)) {
            Q_ASSERT(object == wrappedObjects.value(id).object);
            // check if this transport is already assigned to the object
            if (transport && !wrappedObjects.value(id).transports.contains(transport)) {
                wrappedObjects[id].transports.append(transport);
                transportedWrappedObjects.insert(transport, id);
            }
            classInfo = classInfoForObject(object, transport);
        }

        QJsonObject objectInfo;
        objectInfo[KEY_QOBJECT] = true;
        objectInfo[KEY_ID] = id;
        if (!classInfo.isEmpty())
            objectInfo[KEY_DATA] = classInfo;

        return objectInfo;
    } else if (QMetaType::typeFlags(result.userType()).testFlag(QMetaType::IsEnumeration)) {
        return result.toInt();
    } else if (isQFlagsType(result.userType())) {
        return *reinterpret_cast<const int*>(result.constData());
#ifndef QT_NO_JSVALUE
    } else if (result.canConvert<QJSValue>()) {
        // Workaround for keeping QJSValues from QVariant.
        // Calling QJSValue::toVariant() converts JS-objects/arrays to QVariantMap/List
        // instead of stashing a QJSValue itself into a variant.
        // TODO: Improve QJSValue-QJsonValue conversion in Qt.
        return wrapResult(result.value<QJSValue>().toVariant(), transport, parentObjectId);
#endif
    } else if (result.canConvert<QVariantList>()) {
        // recurse and potentially wrap contents of the array
        // *don't* use result.toList() as that *only* works for QVariantList and QStringList!
        // Also, don't use QSequentialIterable (yet), since that seems to trigger QTBUG-42016
        // in certain cases.
        return wrapList(result.value<QVariantList>(), transport);
    } else if (result.canConvert<QVariantMap>()) {
        // recurse and potentially wrap contents of the map
        return wrapMap(result.toMap(), transport);
    }

    return QJsonValue::fromVariant(result);
}

QJsonArray QMetaObjectPublisher::wrapList(const QVariantList &list, QWebChannelAbstractTransport *transport, const QString &parentObjectId)
{
    QJsonArray array;
    foreach (const QVariant &arg, list) {
        array.append(wrapResult(arg, transport, parentObjectId));
    }
    return array;
}

QJsonObject QMetaObjectPublisher::wrapMap(const QVariantMap &map, QWebChannelAbstractTransport *transport, const QString &parentObjectId)
{
    QJsonObject obj;
    for (QVariantMap::const_iterator i = map.begin(); i != map.end(); i++) {
        obj.insert(i.key(), wrapResult(i.value(), transport, parentObjectId));
    }
    return obj;
}

void QMetaObjectPublisher::deleteWrappedObject(QObject *object) const
{
    if (!wrappedObjects.contains(registeredObjectIds.value(object))) {
        qWarning() << "Not deleting non-wrapped object" << object;
        return;
    }
    object->deleteLater();
}

void QMetaObjectPublisher::broadcastMessage(const QJsonObject &message) const
{
    if (webChannel->d_func()->transports.isEmpty()) {
        qWarning("QWebChannel is not connected to any transports, cannot send message: %s", QJsonDocument(message).toJson().constData());
        return;
    }

    foreach (QWebChannelAbstractTransport *transport, webChannel->d_func()->transports) {
        transport->sendMessage(message);
    }
}

void QMetaObjectPublisher::handleMessage(const QJsonObject &message, QWebChannelAbstractTransport *transport)
{
    if (!webChannel->d_func()->transports.contains(transport)) {
        qWarning() << "Refusing to handle message of unknown transport:" << transport;
        return;
    }

    if (!message.contains(KEY_TYPE)) {
        qWarning("JSON message object is missing the type property: %s", QJsonDocument(message).toJson().constData());
        return;
    }

    const MessageType type = toType(message.value(KEY_TYPE));
    if (type == TypeIdle) {
        setClientIsIdle(true);
    } else if (type == TypeInit) {
        if (!message.contains(KEY_ID)) {
            qWarning("JSON message object is missing the id property: %s",
                      QJsonDocument(message).toJson().constData());
            return;
        }
        transport->sendMessage(createResponse(message.value(KEY_ID), initializeClient(transport)));
    } else if (type == TypeDebug) {
        static QTextStream out(stdout);
        out << "DEBUG: " << message.value(KEY_DATA).toString() << endl;
    } else if (message.contains(KEY_OBJECT)) {
        const QString &objectName = message.value(KEY_OBJECT).toString();
        QObject *object = registeredObjects.value(objectName);
        if (!object)
            object = wrappedObjects.value(objectName).object;

        if (!object) {
            qWarning() << "Unknown object encountered" << objectName;
            return;
        }

        if (type == TypeInvokeMethod) {
            if (!message.contains(KEY_ID)) {
                qWarning("JSON message object is missing the id property: %s",
                          QJsonDocument(message).toJson().constData());
                return;
            }

            QPointer<QMetaObjectPublisher> publisherExists(this);
            QPointer<QWebChannelAbstractTransport> transportExists(transport);
            QJsonValue method = message.value(KEY_METHOD);
            QVariant result;

            if (method.isString()) {
                result = invokeMethod(object,
                                      method.toString().toUtf8(),
                                      message.value(KEY_ARGS).toArray());
            } else {
                result = invokeMethod(object,
                                      method.toInt(-1),
                                      message.value(KEY_ARGS).toArray());
            }
            if (!publisherExists || !transportExists)
                return;
            transport->sendMessage(createResponse(message.value(KEY_ID), wrapResult(result, transport)));
        } else if (type == TypeConnectToSignal) {
            signalHandler.connectTo(object, message.value(KEY_SIGNAL).toInt(-1));
        } else if (type == TypeDisconnectFromSignal) {
            signalHandler.disconnectFrom(object, message.value(KEY_SIGNAL).toInt(-1));
        } else if (type == TypeSetProperty) {
            setProperty(object, message.value(KEY_PROPERTY).toInt(-1),
                        message.value(KEY_VALUE));
        }
    }
}

void QMetaObjectPublisher::setBlockUpdates(bool block)
{
    if (blockUpdates == block) {
        return;
    }
    blockUpdates = block;

    if (!blockUpdates) {
        sendPendingPropertyUpdates();
    } else if (timer.isActive()) {
        timer.stop();
    }

    emit blockUpdatesChanged(block);
}

void QMetaObjectPublisher::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == timer.timerId()) {
        sendPendingPropertyUpdates();
    } else {
        QObject::timerEvent(event);
    }
}

QT_END_NAMESPACE
