/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtScxml 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 "qscxmlglobals_p.h"
#include "qscxmlecmascriptdatamodel.h"
#include "qscxmlecmascriptplatformproperties_p.h"
#include "qscxmlexecutablecontent_p.h"
#include "qscxmlstatemachine_p.h"
#include "qscxmldatamodel_p.h"

#include <qjsengine.h>
#include <qjsondocument.h>
#include <QtQml/private/qjsvalue_p.h>
#include <QtQml/private/qv4scopedvalue_p.h>

#include <functional>

QT_BEGIN_NAMESPACE

using namespace QScxmlExecutableContent;

typedef std::function<QString (bool *)> ToStringEvaluator;
typedef std::function<bool (bool *)> ToBoolEvaluator;
typedef std::function<QVariant (bool *)> ToVariantEvaluator;
typedef std::function<void (bool *)> ToVoidEvaluator;
typedef std::function<bool (bool *, std::function<bool ()>)> ForeachEvaluator;

class QScxmlEcmaScriptDataModelPrivate : public QScxmlDataModelPrivate
{
    Q_DECLARE_PUBLIC(QScxmlEcmaScriptDataModel)
public:
    QScxmlEcmaScriptDataModelPrivate()
        : jsEngine(nullptr)
    {}

    QString evalStr(const QString &expr, const QString &context, bool *ok)
    {
        QString script = QStringLiteral("(%1).toString()").arg(expr);
        QJSValue v = eval(script, context, ok);
        if (*ok)
            return v.toString();
        else
            return QString();
    }

    bool evalBool(const QString &expr, const QString &context, bool *ok)
    {
        QString script = QStringLiteral("(function(){return !!(%1); })()").arg(expr);
        QJSValue v = eval(script, context, ok);
        if (*ok)
            return v.toBool();
        else
            return false;
    }

    QJSValue evalJSValue(const QString &expr, const QString &context, bool *ok)
    {
        assertEngine();

        QString script = QStringLiteral("(function(){'use strict'; return (\n%1\n); })()").arg(expr);
        return eval(script, context, ok);
    }

    QJSValue eval(const QString &script, const QString &context, bool *ok)
    {
        Q_ASSERT(ok);
        QJSEngine *engine = assertEngine();

        // TODO: copy QJSEngine::evaluate and handle the case of v4->catchException() "our way"

        QJSValue v = engine->evaluate(QStringLiteral("'use strict'; ") + script, QStringLiteral("<expr>"), 0);
        if (v.isError()) {
            *ok = false;
            submitError(QStringLiteral("error.execution"),
                        QStringLiteral("%1 in %2").arg(v.toString(), context));
            return QJSValue(QJSValue::UndefinedValue);
        } else {
            *ok = true;
            return v;
        }
    }

    void setupDataModel()
    {
        QJSEngine *engine = assertEngine();
        dataModel = engine->globalObject();

        qCDebug(qscxmlLog) << m_stateMachine << "initializing the datamodel";
        setupSystemVariables();
    }

    void setupSystemVariables()
    {
        setReadonlyProperty(&dataModel, QStringLiteral("_sessionid"),
                            m_stateMachine->sessionId());

        setReadonlyProperty(&dataModel, QStringLiteral("_name"), m_stateMachine->name());

        QJSEngine *engine = assertEngine();
        auto scxml = engine->newObject();
        scxml.setProperty(QStringLiteral("location"), QStringLiteral("#_scxml_%1")
                          .arg(m_stateMachine->sessionId()));
        auto ioProcs = engine->newObject();
        setReadonlyProperty(&ioProcs, QStringLiteral("scxml"), scxml);
        setReadonlyProperty(&dataModel, QStringLiteral("_ioprocessors"), ioProcs);

        auto platformVars = QScxmlPlatformProperties::create(engine, m_stateMachine);
        dataModel.setProperty(QStringLiteral("_x"), platformVars->jsValue());

        dataModel.setProperty(QStringLiteral("In"), engine->evaluate(
                                  QStringLiteral("(function(id){return _x.inState(id);})")));
    }

    void assignEvent(const QScxmlEvent &event)
    {
        if (event.name().isEmpty())
            return;

        QJSEngine *engine = assertEngine();
        QJSValue _event = engine->newObject();
        QJSValue dataValue = eventDataAsJSValue(event.data());
        _event.setProperty(QStringLiteral("data"), dataValue.isUndefined() ? QJSValue(QJSValue::UndefinedValue)
                                                                           : dataValue);
        _event.setProperty(QStringLiteral("invokeid"), event.invokeId().isEmpty() ? QJSValue(QJSValue::UndefinedValue)
                                                                                  : engine->toScriptValue(event.invokeId()));
        if (!event.originType().isEmpty())
            _event.setProperty(QStringLiteral("origintype"), engine->toScriptValue(event.originType()));
        _event.setProperty(QStringLiteral("origin"), event.origin().isEmpty() ? QJSValue(QJSValue::UndefinedValue)
                                                                              : engine->toScriptValue(event.origin()) );
        _event.setProperty(QStringLiteral("sendid"), event.sendId().isEmpty() ? QJSValue(QJSValue::UndefinedValue)
                                                                              : engine->toScriptValue(event.sendId()));
        _event.setProperty(QStringLiteral("type"), engine->toScriptValue(event.scxmlType()));
        _event.setProperty(QStringLiteral("name"), engine->toScriptValue(event.name()));
        _event.setProperty(QStringLiteral("raw"), QStringLiteral("unsupported")); // See test178
        if (event.isErrorEvent())
            _event.setProperty(QStringLiteral("errorMessage"), event.errorMessage());

        setReadonlyProperty(&dataModel, QStringLiteral("_event"), _event);
    }

    QJSValue eventDataAsJSValue(const QVariant &eventData)
    {
        if (!eventData.isValid()) {
            return QJSValue(QJSValue::UndefinedValue);
        }

        QJSEngine *engine = assertEngine();
        if (eventData.canConvert<QVariantMap>()) {
            auto keyValues = eventData.value<QVariantMap>();
            auto data = engine->newObject();

            for (QVariantMap::const_iterator it = keyValues.begin(), eit = keyValues.end(); it != eit; ++it) {
                data.setProperty(it.key(), engine->toScriptValue(it.value()));
            }

            return data;
        }

        if (eventData == QVariant(QMetaType::VoidStar, 0)) {
            return QJSValue(QJSValue::NullValue);
        }

        QString data = eventData.toString();
        QJsonParseError err;
        QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8(), &err);
        if (err.error == QJsonParseError::NoError)
            return engine->toScriptValue(doc.toVariant());
        else
            return engine->toScriptValue(data);
    }

    QJSEngine *assertEngine()
    {
        if (!jsEngine) {
            Q_Q(QScxmlEcmaScriptDataModel);
            setEngine(new QJSEngine(q->stateMachine()));
        }

        return jsEngine;
    }

    QJSEngine *engine() const
    {
        return jsEngine;
    }

    void setEngine(QJSEngine *engine)
    { jsEngine = engine; }

    QString string(StringId id) const
    {
        return m_stateMachine->tableData()->string(id);
    }

    bool hasProperty(const QString &name) const
    { return dataModel.hasProperty(name); }

    QJSValue property(const QString &name) const
    { return dataModel.property(name); }

    bool setProperty(const QString &name, const QJSValue &value, const QString &context)
    {
        QString msg;
        switch (setProperty(&dataModel, name, value)) {
        case SetPropertySucceeded:
            return true;
        case SetReadOnlyPropertyFailed:
            msg = QStringLiteral("cannot assign to read-only property %1 in %2");
            break;
        case SetUnknownPropertyFailed:
            msg = QStringLiteral("cannot assign to unknown propety %1 in %2");
            break;
        case SetPropertyFailedForAnotherReason:
            msg = QStringLiteral("assignment to property %1 failed in %2");
            break;
        default:
            Q_UNREACHABLE();
        }

        submitError(QStringLiteral("error.execution"), msg.arg(name, context));
        return false;
    }

    void submitError(const QString &type, const QString &msg, const QString &sendid = QString())
    {
        QScxmlStateMachinePrivate::get(m_stateMachine)->submitError(type, msg, sendid);
    }

public:
    QStringList initialDataNames;

private: // Uses private API
    static void setReadonlyProperty(QJSValue *object, const QString &name, const QJSValue &value)
    {
        qCDebug(qscxmlLog) << "setting read-only property" << name;
        QV4::ExecutionEngine *engine = QJSValuePrivate::engine(object);
        Q_ASSERT(engine);
        QV4::Scope scope(engine);

        QV4::ScopedObject o(scope, QJSValuePrivate::getValue(object));
        if (!o)
            return;

        if (!QJSValuePrivate::checkEngine(engine, value)) {
            qCWarning(qscxmlLog, "EcmaScriptDataModel::setReadonlyProperty(%s) failed: cannot set value created in a different engine", name.toUtf8().constData());
            return;
        }

        QV4::ScopedString s(scope, engine->newString(name));
        QV4::ScopedPropertyKey key(scope, s->toPropertyKey());
        if (key->isArrayIndex()) {
            Q_UNIMPLEMENTED();
            return;
        }

        QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
        o->defineReadonlyProperty(s, v);
        if (engine->hasException)
            engine->catchException();
    }

    enum SetPropertyResult {
        SetPropertySucceeded,
        SetReadOnlyPropertyFailed,
        SetUnknownPropertyFailed,
        SetPropertyFailedForAnotherReason,
    };

    static SetPropertyResult setProperty(QJSValue *object, const QString &name, const QJSValue &value)
    {
        QV4::ExecutionEngine *engine = QJSValuePrivate::engine(object);
        Q_ASSERT(engine);
        if (engine->hasException)
            return SetPropertyFailedForAnotherReason;

        QV4::Scope scope(engine);
        QV4::ScopedObject o(scope, QJSValuePrivate::getValue(object));
        if (o == nullptr) {
            return SetPropertyFailedForAnotherReason;
        }

        QV4::ScopedString s(scope, engine->newString(name));
        QV4::ScopedPropertyKey key(scope, s->toPropertyKey());
        if (key->isArrayIndex()) {
            Q_UNIMPLEMENTED();
            return SetPropertyFailedForAnotherReason;
        }

        QV4::PropertyAttributes attrs = o->getOwnProperty(s->toPropertyKey());
        if (attrs.isWritable() || attrs.isEmpty()) {
            QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
            o->insertMember(s, v);
            if (engine->hasException) {
                engine->catchException();
                return SetPropertyFailedForAnotherReason;
            } else {
                return SetPropertySucceeded;
            }
        } else {
            return SetReadOnlyPropertyFailed;
        }
    }

private:
    QJSEngine *jsEngine;
    QJSValue dataModel;
};

/*!
 * \class QScxmlEcmaScriptDataModel
 * \brief The QScxmlEcmaScriptDataModel class is the ECMAScript data model for
 * a Qt SCXML state machine.
 * \since 5.7
 * \inmodule QtScxml
 *
 * This class implements the ECMAScript data model as described in
 * \l {SCXML Specification - B.2 The ECMAScript Data Model}. It can be
 * subclassed to perform custom initialization.
 *
 * \sa QScxmlStateMachine QScxmlDataModel
 */

/*!
 * Creates a new ECMAScript data model, with the parent object \a parent.
 */
QScxmlEcmaScriptDataModel::QScxmlEcmaScriptDataModel(QObject *parent)
    : QScxmlDataModel(*(new QScxmlEcmaScriptDataModelPrivate), parent)
{}

/*!
  \reimp
 */
bool QScxmlEcmaScriptDataModel::setup(const QVariantMap &initialDataValues)
{
    Q_D(QScxmlEcmaScriptDataModel);
    d->setupDataModel();

    bool ok = true;
    QJSValue undefined(QJSValue::UndefinedValue); // See B.2.1, and test456.
    int count;
    StringId *names = d->m_stateMachine->tableData()->dataNames(&count);
    for (int i = 0; i < count; ++i) {
        auto name = d->string(names[i]);
        QJSValue v = undefined;
        QVariantMap::const_iterator it = initialDataValues.find(name);
        if (it != initialDataValues.end()) {
            QJSEngine *engine = d->assertEngine();
            v = engine->toScriptValue(it.value());
        }
        if (!d->setProperty(name, v, QStringLiteral("<data>"))) {
            ok = false;
        }
    }
    d->initialDataNames = initialDataValues.keys();

    return ok;
}

/*!
  \reimp
 */
QString QScxmlEcmaScriptDataModel::evaluateToString(QScxmlExecutableContent::EvaluatorId id,
                                                    bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    const EvaluatorInfo &info = d->m_stateMachine->tableData()->evaluatorInfo(id);

    return d->evalStr(d->string(info.expr), d->string(info.context), ok);
}

/*!
  \reimp
 */
bool QScxmlEcmaScriptDataModel::evaluateToBool(QScxmlExecutableContent::EvaluatorId id,
                                               bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    const EvaluatorInfo &info = d->m_stateMachine->tableData()->evaluatorInfo(id);

    return d->evalBool(d->string(info.expr), d->string(info.context), ok);
}

/*!
  \reimp
 */
QVariant QScxmlEcmaScriptDataModel::evaluateToVariant(QScxmlExecutableContent::EvaluatorId id,
                                                      bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    const EvaluatorInfo &info = d->m_stateMachine->tableData()->evaluatorInfo(id);

    return d->evalJSValue(d->string(info.expr), d->string(info.context), ok).toVariant();
}

/*!
  \reimp
 */
void QScxmlEcmaScriptDataModel::evaluateToVoid(QScxmlExecutableContent::EvaluatorId id,
                                               bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    const EvaluatorInfo &info = d->m_stateMachine->tableData()->evaluatorInfo(id);

    d->eval(d->string(info.expr), d->string(info.context), ok);
}

/*!
  \reimp
 */
void QScxmlEcmaScriptDataModel::evaluateAssignment(QScxmlExecutableContent::EvaluatorId id,
                                                   bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    Q_ASSERT(ok);

    const AssignmentInfo &info = d->m_stateMachine->tableData()->assignmentInfo(id);

    QString dest = d->string(info.dest);

    if (hasScxmlProperty(dest)) {
        QJSValue v = d->evalJSValue(d->string(info.expr), d->string(info.context), ok);
        if (*ok)
            *ok = d->setProperty(dest, v, d->string(info.context));
    } else {
        *ok = false;
        d->submitError(QStringLiteral("error.execution"),
                       QStringLiteral("%1 in %2 does not exist").arg(dest, d->string(info.context)));
    }
}

/*!
  \reimp
 */
void QScxmlEcmaScriptDataModel::evaluateInitialization(QScxmlExecutableContent::EvaluatorId id,
                                                       bool *ok)
{
    Q_D(QScxmlEcmaScriptDataModel);
    const AssignmentInfo &info = d->m_stateMachine->tableData()->assignmentInfo(id);
    QString dest = d->string(info.dest);
    if (d->initialDataNames.contains(dest)) {
        *ok = true; // silently ignore the <data> tag
        return;
    }

    evaluateAssignment(id, ok);
}

/*!
  \reimp
 */
void QScxmlEcmaScriptDataModel::evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok,
                                                ForeachLoopBody *body)
{
    Q_D(QScxmlEcmaScriptDataModel);
    Q_ASSERT(ok);
    Q_ASSERT(body);
    const ForeachInfo &info = d->m_stateMachine->tableData()->foreachInfo(id);

    QJSValue jsArray = d->property(d->string(info.array));
    if (!jsArray.isArray()) {
        d->submitError(QStringLiteral("error.execution"), QStringLiteral("invalid array '%1' in %2").arg(d->string(info.array), d->string(info.context)));
        *ok = false;
        return;
    }

    QString item = d->string(info.item);

    QJSEngine *engine = d->assertEngine();
    if (engine->evaluate(QStringLiteral("(function(){var %1 = 0})()").arg(item)).isError()) {
        d->submitError(QStringLiteral("error.execution"), QStringLiteral("invalid item '%1' in %2")
                      .arg(d->string(info.item), d->string(info.context)));
        *ok = false;
        return;
    }

    const int length = jsArray.property(QStringLiteral("length")).toInt();
    QString idx = d->string(info.index);
    QString context = d->string(info.context);
    const bool hasIndex = !idx.isEmpty();

    for (int currentIndex = 0; currentIndex < length; ++currentIndex) {
        QJSValue currentItem = jsArray.property(static_cast<quint32>(currentIndex));
        *ok = d->setProperty(item, currentItem, context);
        if (!*ok)
            return;
        if (hasIndex) {
            *ok = d->setProperty(idx, currentIndex, context);
            if (!*ok)
                return;
        }
        body->run(ok);
        if (!*ok)
            return;
    }
    *ok = true;
}

/*!
 * \reimp
 */
void QScxmlEcmaScriptDataModel::setScxmlEvent(const QScxmlEvent &event)
{
    Q_D(QScxmlEcmaScriptDataModel);
    d->assignEvent(event);
}

/*!
 * \reimp
 */
QVariant QScxmlEcmaScriptDataModel::scxmlProperty(const QString &name) const
{
    Q_D(const QScxmlEcmaScriptDataModel);
    return d->property(name).toVariant();
}

/*!
 * \reimp
 */
bool QScxmlEcmaScriptDataModel::hasScxmlProperty(const QString &name) const
{
    Q_D(const QScxmlEcmaScriptDataModel);
    return d->hasProperty(name);
}

/*!
 * \reimp
 */
bool QScxmlEcmaScriptDataModel::setScxmlProperty(const QString &name, const QVariant &value,
                                                 const QString &context)
{
    Q_D(QScxmlEcmaScriptDataModel);
    Q_ASSERT(hasScxmlProperty(name));

    QJSEngine *engine = d->assertEngine();
    QJSValue v = engine->toScriptValue(
                value.canConvert<QJSValue>() ? value.value<QJSValue>().toVariant() : value);
    return d->setProperty(name, v, context);
}

QT_END_NAMESPACE
