/****************************************************************************
**
** 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 "qscxmlstatemachine_p.h"
#include "qscxmlexecutablecontent_p.h"
#include "qscxmlevent_p.h"
#include "qscxmlinvokableservice.h"
#include "qscxmldatamodel_p.h"

#include <qfile.h>
#include <qhash.h>
#include <qloggingcategory.h>
#include <qstring.h>
#include <qtimer.h>
#include <qthread.h>

#include <functional>

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(qscxmlLog, "qt.scxml.statemachine")
Q_LOGGING_CATEGORY(scxmlLog, "scxml.statemachine")

/*!
 * \class QScxmlStateMachine
 * \brief The QScxmlStateMachine class provides an interface to the state machines
 * created from SCXML files.
 * \since 5.7
 * \inmodule QtScxml
 *
 * QScxmlStateMachine is an implementation of the
 * \l{SCXML Specification}{State Chart XML (SCXML)}.
 *
 * All states that are defined in the SCXML file
 * are accessible as properties of QScxmlStateMachine.
 * These properties are boolean values and indicate
 * whether the state is active or inactive.
 *
 * \note The QScxmlStateMachine needs a QEventLoop to work correctly. The event loop is used to
 *       implement the \c delay attribute for events and to schedule the processing of a state
 *       machine when events are received from nested (or parent) state machines.
 */

/*!
    \qmltype ScxmlStateMachine
    \instantiates QScxmlStateMachine
    \inqmlmodule QtScxml
    \since 5.7

    \brief Provides an interface to the state machines created from SCXML files.

    The ScxmlStateMachine type is an implementation of the
    \l{SCXML Specification}{State Chart XML (SCXML)}.

    All states that are defined in the SCXML file are accessible as properties
    of this type. These properties are boolean values and indicate whether the
    state is active or inactive.
*/

/*!
    \fn template<typename PointerToMemberFunction> QMetaObject::Connection QScxmlStateMachine::connectToEvent(
                                           const QString &scxmlEventSpec,
                                           const typename QtPrivate::FunctionPointer<PointerToMemberFunction>::Object *receiver,
                                           PointerToMemberFunction method,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the event specified by
    \a scxmlEventSpec to \a method in the \a receiver object.

    The receiver's \a method must take a QScxmlEvent as a parameter.

    In contrast to event specifications in SCXML documents, spaces are not
    allowed in the \a scxmlEventSpec here. In order to connect to multiple
    events with different prefixes, connectToEvent() has to be called multiple
    times.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn template<typename Functor> typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Functor>::IsPointerToMemberFunction && !std::is_same<const char*, Functor>::value, QMetaObject::Connection>::Type QScxmlStateMachine::connectToEvent(
                                           const QString &scxmlEventSpec,
                                           Functor functor,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the event specified by
    \a scxmlEventSpec to \a functor.

    The \a functor must take a QScxmlEvent as a parameter.

    In contrast to event specifications in SCXML documents, spaces are not
    allowed in the \a scxmlEventSpec here. In order to connect to multiple
    events with different prefixes, connectToEvent() has to be called multiple
    times.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn template<typename Functor> typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Functor>::IsPointerToMemberFunction && !std::is_same<const char*, Functor>::value, QMetaObject::Connection>::Type QScxmlStateMachine::connectToEvent(
                                           const QString &scxmlEventSpec,
                                           const QObject *context,
                                           Functor functor,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the event specified by
    \a scxmlEventSpec to \a functor using \a context as context.

    The \a functor must take a QScxmlEvent as a parameter.

    In contrast to event specifications in SCXML documents, spaces are not
    allowed in the \a scxmlEventSpec here. In order to connect to multiple
    events with different prefixes, connectToEvent() has to be called multiple
    times.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn template<typename PointerToMemberFunction> QMetaObject::Connection QScxmlStateMachine::connectToState(
                                           const QString &scxmlStateName,
                                           const typename QtPrivate::FunctionPointer<PointerToMemberFunction>::Object *receiver,
                                           PointerToMemberFunction method,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the state specified by
    \a scxmlStateName to \a method in the \a receiver object.

    The receiver's \a method must take a boolean argument that indicates
    whether the state connected became active or inactive.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn template<typename Functor> typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Functor>::IsPointerToMemberFunction && !std::is_same<const char*, Functor>::value, QMetaObject::Connection>::Type QScxmlStateMachine::connectToState(
                                           const QString &scxmlStateName,
                                           Functor functor,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the state specified by
    \a scxmlStateName to \a functor.

    The \a functor must take a boolean argument that indicates whether the
    state connected became active or inactive.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn template<typename Functor> typename QtPrivate::QEnableIf<!QtPrivate::FunctionPointer<Functor>::IsPointerToMemberFunction && !std::is_same<const char*, Functor>::value, QMetaObject::Connection>::Type QScxmlStateMachine::connectToState(
                                           const QString &scxmlStateName,
                                           const QObject *context,
                                           Functor functor,
                                           Qt::ConnectionType type)

    Creates a connection of the given \a type from the state specified by
    \a scxmlStateName to \a functor using \a context as context.

    The \a functor must take a boolean argument that indicates whether the
    state connected became active or inactive.

    Returns a handle to the connection, which can be used later to disconnect.
*/

/*!
    \fn std::function<void(bool)> QScxmlStateMachine::onEntry(
            const QObject *receiver, const char *method)

    Returns a functor that accepts a boolean argument and calls the given
    \a method on \a receiver using QMetaObject::invokeMethod() if that argument
    is \c true and \a receiver has not been deleted, yet.

    The given \a method must not accept any arguments. \a method is the plain
    method name, not enclosed in \c SIGNAL() or \c SLOT().

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is entered.
 */

/*!
    \fn std::function<void(bool)> QScxmlStateMachine::onExit(
            const QObject *receiver, const char *method)

    Returns a functor that accepts a boolean argument and calls the given
    \a method on \a receiver using QMetaObject::invokeMethod() if that argument
    is \c false and \a receiver has not been deleted, yet.

    The given \a method must not accept any arguments. \a method is the plain
    method name, not enclosed in SIGNAL(...) or SLOT(...).

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is left.
 */

/*!
    \fn template<typename Functor> std::function<void(bool)> QScxmlStateMachine::onEntry(
            Functor functor)

    Returns a functor that accepts a boolean argument and calls the given
    \a functor if that argument is \c true. The given \a functor must not
    accept any arguments.

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is entered.
 */

/*!
    \fn template<typename Functor> std::function<void(bool)> QScxmlStateMachine::onExit(Functor functor)

    Returns a functor that accepts a boolean argument and calls the given
    \a functor if that argument is \c false. The given \a functor must not
    accept any arguments.

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is left.
 */

/*!
    \fn template<typename PointerToMemberFunction> std::function<void(bool)> QScxmlStateMachine::onEntry(
            const typename QtPrivate::FunctionPointer<PointerToMemberFunction>::Object *receiver,
            PointerToMemberFunction method)

    Returns a functor that accepts a boolean argument and calls the given
    \a method on \a receiver if that argument is \c true and the \a receiver
    has not been deleted, yet. The given \a method must not accept any
    arguments.

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is entered.
 */

/*!
    \fn template<typename PointerToMemberFunction> std::function<void(bool)> QScxmlStateMachine::onExit(
            const typename QtPrivate::FunctionPointer<PointerToMemberFunction>::Object *receiver,
            PointerToMemberFunction method)

    Returns a functor that accepts a boolean argument and calls the given
    \a method on \a receiver if that argument is \c false and the \a receiver
    has not been deleted, yet. The given \a method must not accept any
    arguments.

    This is useful to wrap handlers for connectToState() that should only
    be executed when the state is left.
 */

namespace QScxmlInternal {

static int signalIndex(const QMetaObject *meta, const QByteArray &signalName)
{
    Q_ASSERT(meta);

    int signalIndex = meta->indexOfSignal(signalName.constData());

    // If signal doesn't exist, return negative value
    if (signalIndex < 0)
        return signalIndex;

    // signal belongs to class whose meta object was passed, not some derived class.
    Q_ASSERT(meta->methodOffset() <= signalIndex);

    // Duplicate of computeOffsets in qobject.cpp
    const QMetaObject *m = meta->d.superdata;
    while (m) {
        const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
        signalIndex = signalIndex - d->methodCount + d->signalCount;
        m = m->d.superdata;
    }

    // Asserting about the signal not being cloned would be nice, too, but not practical.

    return signalIndex;
}

void EventLoopHook::queueProcessEvents()
{
    if (smp->m_isProcessingEvents)
        return;

    QMetaObject::invokeMethod(this, "doProcessEvents", Qt::QueuedConnection);
}

void EventLoopHook::doProcessEvents()
{
    smp->processEvents();
}

void EventLoopHook::timerEvent(QTimerEvent *timerEvent)
{
    const int timerId = timerEvent->timerId();
    for (auto it = smp->m_delayedEvents.begin(), eit = smp->m_delayedEvents.end(); it != eit; ++it) {
        if (it->first == timerId) {
            QScxmlEvent *scxmlEvent = it->second;
            smp->m_delayedEvents.erase(it);
            smp->routeEvent(scxmlEvent);
            killTimer(timerId);
            return;
        }
    }
}

void ScxmlEventRouter::route(const QStringList &segments, QScxmlEvent *event)
{
    emit eventOccurred(*event);
    if (!segments.isEmpty()) {
        auto it = children.find(segments.first());
        if (it != children.end())
            it.value()->route(segments.mid(1), event);
    }
}

static QString nextSegment(const QStringList &segments)
{
    if (segments.isEmpty())
        return QString();

    const QString &segment = segments.first();
    return segment == QLatin1String("*") ? QString() : segment;
}

ScxmlEventRouter *ScxmlEventRouter::child(const QString &segment)
{
    ScxmlEventRouter *&child = children[segment];
    if (child == nullptr)
        child = new ScxmlEventRouter(this);
    return child;
}

void ScxmlEventRouter::disconnectNotify(const QMetaMethod &signal)
{
    Q_UNUSED(signal);

    // Defer the actual work, as this may be called from a destructor, or the signal may not
    // actually be disconnected, yet.
    QTimer::singleShot(0, this, [this] {
        if (!children.isEmpty() || receivers(SIGNAL(eventOccurred(QScxmlEvent))) > 0)
            return;

        ScxmlEventRouter *parentRouter = qobject_cast<ScxmlEventRouter *>(parent());
        if (!parentRouter) // root node
            return;

        QHash<QString, ScxmlEventRouter *>::Iterator it = parentRouter->children.begin(),
                end = parentRouter->children.end();
        for (; it != end; ++it) {
            if (it.value() == this) {
                parentRouter->children.erase(it);
                parentRouter->disconnectNotify(QMetaMethod());
                break;
            }
        }

        deleteLater(); // The parent might delete itself, triggering QObject delete cascades.
    });
}

QMetaObject::Connection ScxmlEventRouter::connectToEvent(const QStringList &segments,
                                                         const QObject *receiver,
                                                         const char *method,
                                                         Qt::ConnectionType type)
{
    QString segment = nextSegment(segments);
    return segment.isEmpty() ?
                connect(this, SIGNAL(eventOccurred(QScxmlEvent)), receiver, method, type) :
                child(segment)->connectToEvent(segments.mid(1), receiver, method, type);
}

QMetaObject::Connection ScxmlEventRouter::connectToEvent(const QStringList &segments,
                                                         const QObject *receiver, void **slot,
                                                         QtPrivate::QSlotObjectBase *method,
                                                         Qt::ConnectionType type)
{
    QString segment = nextSegment(segments);
    if (segment.isEmpty()) {
        const int *types = nullptr;
        if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
            types = QtPrivate::ConnectionTypes<QtPrivate::List<QScxmlEvent> >::types();

        const QMetaObject *meta = metaObject();
        static const int eventOccurredIndex = signalIndex(meta, "eventOccurred(QScxmlEvent)");
        return QObjectPrivate::connectImpl(this, eventOccurredIndex, receiver, slot, method, type,
                                           types, meta);
    } else {
        return child(segment)->connectToEvent(segments.mid(1), receiver, slot, method, type);
    }
}

} // namespace QScxmlInternal

QAtomicInt QScxmlStateMachinePrivate::m_sessionIdCounter = QAtomicInt(0);

QScxmlStateMachinePrivate::QScxmlStateMachinePrivate(const QMetaObject *metaObject)
    : QObjectPrivate()
    , m_sessionId(QScxmlStateMachinePrivate::generateSessionId(QStringLiteral("session-")))
    , m_isInvoked(false)
    , m_isInitialized(false)
    , m_isProcessingEvents(false)
    , m_dataModel(nullptr)
    , m_loader(&m_defaultLoader)
    , m_executionEngine(nullptr)
    , m_tableData(nullptr)
    , m_parentStateMachine(nullptr)
    , m_eventLoopHook(this)
    , m_metaObject(metaObject)
    , m_infoSignalProxy(nullptr)
{
    static int metaType = qRegisterMetaType<QScxmlStateMachine *>();
    Q_UNUSED(metaType);
}

QScxmlStateMachinePrivate::~QScxmlStateMachinePrivate()
{
    for (const InvokedService &invokedService : m_invokedServices)
        delete invokedService.service;
    qDeleteAll(m_cachedFactories);
    delete m_executionEngine;
}

QScxmlStateMachinePrivate::ParserData *QScxmlStateMachinePrivate::parserData()
{
    if (m_parserData.isNull())
        m_parserData.reset(new ParserData);
    return m_parserData.data();
}

void QScxmlStateMachinePrivate::addService(int invokingState)
{
    Q_Q(QScxmlStateMachine);

    const int arrayId = m_stateTable->state(invokingState).serviceFactoryIds;
    if (arrayId == StateTable::InvalidIndex)
        return;

    const auto &ids = m_stateTable->array(arrayId);
    for (int id : ids) {
        auto factory = serviceFactory(id);
        auto service = factory->invoke(q);
        if (service == nullptr)
            continue; // service failed to start
        const QString serviceName = service->name();
        m_invokedServices[size_t(id)] = { invokingState, service, serviceName };
        service->start();
    }
    emitInvokedServicesChanged();
}

void QScxmlStateMachinePrivate::removeService(int invokingState)
{
    const int arrayId = m_stateTable->state(invokingState).serviceFactoryIds;
    if (arrayId == StateTable::InvalidIndex)
        return;

    for (size_t i = 0, ei = m_invokedServices.size(); i != ei; ++i) {
        auto &it = m_invokedServices[i];
        QScxmlInvokableService *service = it.service;
        if (it.invokingState == invokingState && service != nullptr) {
            it.service = nullptr;
            delete service;
        }
    }
    emitInvokedServicesChanged();
}

QScxmlInvokableServiceFactory *QScxmlStateMachinePrivate::serviceFactory(int id)
{
    Q_ASSERT(id <= m_stateTable->maxServiceId && id >= 0);
    QScxmlInvokableServiceFactory *& factory = m_cachedFactories[size_t(id)];
    if (factory == nullptr)
        factory = m_tableData->serviceFactory(id);
    return factory;
}

bool QScxmlStateMachinePrivate::executeInitialSetup()
{
    return m_executionEngine->execute(m_tableData->initialSetup());
}

void QScxmlStateMachinePrivate::routeEvent(QScxmlEvent *event)
{
    Q_Q(QScxmlStateMachine);

    if (!event)
        return;

    QString origin = event->origin();
    if (origin == QStringLiteral("#_parent")) {
        if (auto psm = m_parentStateMachine) {
            qCDebug(qscxmlLog) << q << "routing event" << event->name() << "from" << q->name() << "to parent" << psm->name();
                                 QScxmlStateMachinePrivate::get(psm)->postEvent(event);
        } else {
            qCDebug(qscxmlLog) << this << "is not invoked, so it cannot route a message to #_parent";
            delete event;
        }
    } else if (origin.startsWith(QStringLiteral("#_")) && origin != QStringLiteral("#_internal")) {
        // route to children
        auto originId = origin.midRef(2);
        for (const auto &invokedService : m_invokedServices) {
            auto service = invokedService.service;
            if (service == nullptr)
                continue;
            if (service->id() == originId) {
                qCDebug(qscxmlLog) << q << "routing event" << event->name()
                                   << "from" << q->name()
                                   << "to child" << service->id();
                service->postEvent(new QScxmlEvent(*event));
            }
        }
        delete event;
    } else {
        postEvent(event);
    }
}

void QScxmlStateMachinePrivate::postEvent(QScxmlEvent *event)
{
    Q_Q(QScxmlStateMachine);

    if (!event->name().startsWith(QStringLiteral("done.invoke."))) {
        for (int id = 0, end = static_cast<int>(m_invokedServices.size()); id != end; ++id) {
            auto service = m_invokedServices[id].service;
            if (service == nullptr)
                continue;
            auto factory = serviceFactory(id);
            if (event->invokeId() == service->id()) {
                setEvent(event);

                const QScxmlExecutableContent::ContainerId finalize
                        = factory->invokeInfo().finalize;
                if (finalize != QScxmlExecutableContent::NoContainer) {
                    auto psm = service->parentStateMachine();
                    qCDebug(qscxmlLog) << psm << "running finalize on event";
                    auto smp = QScxmlStateMachinePrivate::get(psm);
                    smp->m_executionEngine->execute(finalize);
                }

                resetEvent();
            }
            if (factory->invokeInfo().autoforward) {
                qCDebug(qscxmlLog) << q << "auto-forwarding event" << event->name()
                                   << "from" << q->name()
                                   << "to child" << service->id();
                service->postEvent(new QScxmlEvent(*event));
            }
        }
    }

    if (event->eventType() == QScxmlEvent::ExternalEvent)
        m_router.route(event->name().split(QLatin1Char('.')), event);

    if (event->eventType() == QScxmlEvent::ExternalEvent) {
        qCDebug(qscxmlLog) << q << "posting external event" << event->name();
        m_externalQueue.enqueue(event);
    } else {
        qCDebug(qscxmlLog) << q << "posting internal event" << event->name();
        m_internalQueue.enqueue(event);
    }

    m_eventLoopHook.queueProcessEvents();
}

void QScxmlStateMachinePrivate::submitDelayedEvent(QScxmlEvent *event)
{
    Q_ASSERT(event);
    Q_ASSERT(event->delay() > 0);

    const int timerId = m_eventLoopHook.startTimer(event->delay());
    if (timerId == 0) {
        qWarning("QScxmlStateMachinePrivate::submitDelayedEvent: "
                 "failed to start timer for event '%s' (%p)",
                 qPrintable(event->name()), event);
        delete event;
        return;
    }
    m_delayedEvents.push_back(std::make_pair(timerId, event));

    qCDebug(qscxmlLog) << q_func()
                       << ": delayed event" << event->name()
                       << "(" << event << ") got id:" << timerId;
}

/*!
 * Submits an error event to the external event queue of this state machine.
 *
 * The type of the error is specified by \a type. The value of type has to begin
 * with the string \e error. For example \c {error.execution}. The message,
 * \a message, decribes the error and is passed to the event as the
 * \c errorMessage property. The \a sendId of the message causing the error is specified, if it has
 * one.
 */
void QScxmlStateMachinePrivate::submitError(const QString &type, const QString &message,
                                            const QString &sendId)
{
    Q_Q(QScxmlStateMachine);
    qCDebug(qscxmlLog) << q << "had error" << type << ":" << message;
    if (!type.startsWith(QStringLiteral("error.")))
        qCWarning(qscxmlLog) << q << "Message type of error message does not start with 'error.'!";
    q->submitEvent(QScxmlEventBuilder::errorEvent(q, type, message, sendId));
}

void QScxmlStateMachinePrivate::start()
{
    Q_Q(QScxmlStateMachine);

    if (m_stateTable->binding == StateTable::LateBinding)
        m_isFirstStateEntry.resize(m_stateTable->stateCount, true);

    bool running = isRunnable() && !isPaused();
    m_runningState = Starting;
    Q_ASSERT(m_stateTable->initialTransition != StateTable::InvalidIndex);

    if (!running)
        emit q->runningChanged(true);
}

void QScxmlStateMachinePrivate::pause()
{
    Q_Q(QScxmlStateMachine);

    if (isRunnable() && !isPaused()) {
        m_runningState = Paused;
        emit q->runningChanged(false);
    }
}

void QScxmlStateMachinePrivate::processEvents()
{
    if (m_isProcessingEvents || (!isRunnable() && !isPaused()))
        return;

    m_isProcessingEvents = true;

    Q_Q(QScxmlStateMachine);
    qCDebug(qscxmlLog) << q_func() << "starting macrostep";

    while (isRunnable() && !isPaused()) {
        if (m_runningState == Starting) {
            enterStates({m_stateTable->initialTransition});
            if (m_runningState == Starting)
                m_runningState = Running;
            continue;
        }

        OrderedSet enabledTransitions;
        std::vector<int> configurationInDocumentOrder = m_configuration.list();
        std::sort(configurationInDocumentOrder.begin(), configurationInDocumentOrder.end());
        selectTransitions(enabledTransitions, configurationInDocumentOrder, nullptr);
        if (!enabledTransitions.isEmpty()) {
            microstep(enabledTransitions);
        } else if (!m_internalQueue.isEmpty()) {
            auto event = m_internalQueue.dequeue();
            setEvent(event);
            selectTransitions(enabledTransitions, configurationInDocumentOrder, event);
            if (!enabledTransitions.isEmpty()) {
                microstep(enabledTransitions);
            }
            resetEvent();
            delete event;
        } else if (!m_externalQueue.isEmpty()) {
            auto event = m_externalQueue.dequeue();
            setEvent(event);
            selectTransitions(enabledTransitions, configurationInDocumentOrder, event);
            if (!enabledTransitions.isEmpty()) {
                microstep(enabledTransitions);
            }
            resetEvent();
            delete event;
        } else {
            // nothing to do, so:
            break;
        }
    }

    if (!m_statesToInvoke.empty()) {
        for (int stateId : m_statesToInvoke)
            addService(stateId);
        m_statesToInvoke.clear();
    }

    qCDebug(qscxmlLog) << q_func()
                       << "finished macrostep, runnable:" << isRunnable()
                       << "paused:" << isPaused();
    emit q->reachedStableState();
    if (!isRunnable() && !isPaused()) {
        exitInterpreter();
        emit q->finished();
    }

    m_isProcessingEvents = false;
}

void QScxmlStateMachinePrivate::setEvent(QScxmlEvent *event)
{
    Q_ASSERT(event);
    m_dataModel->setScxmlEvent(*event);
}

void QScxmlStateMachinePrivate::resetEvent()
{
    m_dataModel->setScxmlEvent(QScxmlEvent());
}

void QScxmlStateMachinePrivate::emitStateActive(int stateIndex, bool active)
{
    Q_Q(QScxmlStateMachine);
    void *args[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&active)) };
    const int signalIndex = m_stateIndexToSignalIndex.value(stateIndex, -1);
    if (signalIndex >= 0)
        QMetaObject::activate(q, m_metaObject, signalIndex, args);
}

void QScxmlStateMachinePrivate::emitInvokedServicesChanged()
{
    Q_Q(QScxmlStateMachine);
    emit q->invokedServicesChanged(q->invokedServices());
}

void QScxmlStateMachinePrivate::attach(QScxmlStateMachineInfo *info)
{
    Q_Q(QScxmlStateMachine);

    if (!m_infoSignalProxy)
        m_infoSignalProxy = new QScxmlInternal::StateMachineInfoProxy(q);

    QObject::connect(m_infoSignalProxy, &QScxmlInternal::StateMachineInfoProxy::statesEntered,
                     info, &QScxmlStateMachineInfo::statesEntered);
    QObject::connect(m_infoSignalProxy, &QScxmlInternal::StateMachineInfoProxy::statesExited,
                     info, &QScxmlStateMachineInfo::statesExited);
    QObject::connect(m_infoSignalProxy,&QScxmlInternal::StateMachineInfoProxy::transitionsTriggered,
                     info, &QScxmlStateMachineInfo::transitionsTriggered);
}

void QScxmlStateMachinePrivate::updateMetaCache()
{
    m_stateIndexToSignalIndex.clear();
    m_stateNameToSignalIndex.clear();

    if (!m_tableData)
        return;

    if (!m_stateTable)
        return;

    int signalIndex = 0;
    const int methodOffset = QMetaObjectPrivate::signalOffset(m_metaObject);
    for (int i = 0; i < m_stateTable->stateCount; ++i) {
        const auto &s = m_stateTable->state(i);
        if (!s.isHistoryState() && s.type != StateTable::State::Invalid) {
            m_stateIndexToSignalIndex.insert(i, signalIndex);
            m_stateNameToSignalIndex.insert(m_tableData->string(s.name),
                                            signalIndex + methodOffset);

            ++signalIndex;
        }
    }
}

QStringList QScxmlStateMachinePrivate::stateNames(const std::vector<int> &stateIndexes) const
{
    QStringList names;
    for (int idx : stateIndexes)
        names.append(m_tableData->string(m_stateTable->state(idx).name));
    return names;
}

std::vector<int> QScxmlStateMachinePrivate::historyStates(int stateIdx) const {
    const StateTable::Array kids = m_stateTable->array(m_stateTable->state(stateIdx).childStates);
    std::vector<int> res;
    if (!kids.isValid()) return res;
    for (int k : kids) {
        if (m_stateTable->state(k).isHistoryState())
            res.push_back(k);
    }
    return res;
}

void QScxmlStateMachinePrivate::exitInterpreter()
{
    qCDebug(qscxmlLog) << q_func() << "exiting SCXML processing";

    for (auto it : m_delayedEvents) {
        m_eventLoopHook.killTimer(it.first);
        delete it.second;
    }
    m_delayedEvents.clear();

    auto statesToExitSorted = m_configuration.list();
    std::sort(statesToExitSorted.begin(), statesToExitSorted.end(), std::greater<int>());
    for (int stateIndex : statesToExitSorted) {
        const auto &state = m_stateTable->state(stateIndex);
        if (state.exitInstructions != StateTable::InvalidIndex) {
            m_executionEngine->execute(state.exitInstructions);
        }
        removeService(stateIndex);
        if (state.type == StateTable::State::Final && state.parentIsScxmlElement()) {
            returnDoneEvent(state.doneData);
        }
    }
}

void QScxmlStateMachinePrivate::returnDoneEvent(QScxmlExecutableContent::ContainerId doneData)
{
    Q_Q(QScxmlStateMachine);

    m_executionEngine->execute(doneData, QVariant());
    if (m_isInvoked) {
        auto e = new QScxmlEvent;
        e->setName(QStringLiteral("done.invoke.") + q->sessionId());
        e->setInvokeId(q->sessionId());
        QScxmlStateMachinePrivate::get(m_parentStateMachine)->postEvent(e);
    }
}

bool QScxmlStateMachinePrivate::nameMatch(const StateTable::Array &patterns,
                                          QScxmlEvent *event) const
{
    const QString eventName = event->name();
    bool selected = false;
    for (int eventSelectorIter = 0; eventSelectorIter < patterns.size(); ++eventSelectorIter) {
        QString eventStr = m_tableData->string(patterns[eventSelectorIter]);
        if (eventStr == QStringLiteral("*")) {
            selected = true;
            break;
        }
        if (eventStr.endsWith(QStringLiteral(".*")))
            eventStr.chop(2);
        if (eventName.startsWith(eventStr)) {
            QChar nextC = QLatin1Char('.');
            if (eventName.size() > eventStr.size())
                nextC = eventName.at(eventStr.size());
            if (nextC == QLatin1Char('.') || nextC == QLatin1Char('(')) {
                selected = true;
                break;
            }
        }
    }
    return selected;
}

void QScxmlStateMachinePrivate::selectTransitions(OrderedSet &enabledTransitions,
                                                  const std::vector<int> &configInDocumentOrder,
                                                  QScxmlEvent *event) const
{
    if (event == nullptr) {
        qCDebug(qscxmlLog) << q_func() << "selectEventlessTransitions";
    } else {
        qCDebug(qscxmlLog) << q_func() << "selectTransitions with event"
                           << QScxmlEventPrivate::debugString(event).constData();
    }

    std::vector<int> states;
    states.reserve(16);
    for (int configStateIdx : configInDocumentOrder) {
        if (m_stateTable->state(configStateIdx).isAtomic()) {
            states.clear();
            states.push_back(configStateIdx);
            getProperAncestors(&states, configStateIdx, -1);
            for (int stateIdx : states) {
                bool finishedWithThisConfigState  = false;

                if (stateIdx == -1) {
                    // the state machine has no transitions (other than the initial one, which has
                    // already been taken at this point)
                    continue;
                }
                const auto &state = m_stateTable->state(stateIdx);
                const StateTable::Array transitions = m_stateTable->array(state.transitions);
                if (!transitions.isValid())
                    continue;
                std::vector<int> sortedTransitions(transitions.size(), -1);
                std::copy(transitions.begin(), transitions.end(), sortedTransitions.begin());
                for (int transitionIndex : sortedTransitions) {
                    const StateTable::Transition &t = m_stateTable->transition(transitionIndex);
                    bool enabled = false;
                    if (event == nullptr) {
                        if (t.events == -1) {
                            if (t.condition == -1) {
                                enabled = true;
                            } else {
                                bool ok = false;
                                enabled = m_dataModel->evaluateToBool(t.condition, &ok) && ok;
                            }
                        }
                    } else {
                        if (t.events != -1 && nameMatch(m_stateTable->array(t.events), event)) {
                            if (t.condition == -1) {
                                enabled = true;
                            } else {
                                bool ok = false;
                                enabled = m_dataModel->evaluateToBool(t.condition, &ok) && ok;
                            }
                        }
                    }
                    if (enabled) {
                        enabledTransitions.add(transitionIndex);
                        finishedWithThisConfigState = true;
                        break; // stop iterating over transitions
                    }
                }

                if (finishedWithThisConfigState)
                    break; // stop iterating over ancestors
            }
        }
    }
    if (!enabledTransitions.isEmpty())
        removeConflictingTransitions(&enabledTransitions);
}

void QScxmlStateMachinePrivate::removeConflictingTransitions(OrderedSet *enabledTransitions) const
{
    Q_ASSERT(enabledTransitions);

    auto sortedTransitions = enabledTransitions->takeList();
    std::sort(sortedTransitions.begin(), sortedTransitions.end(), [this](int t1, int t2) -> bool {
        auto descendantDepth = [this](int state, int ancestor)->int {
            int depth = 0;
            for (int it = state; it != -1; it = m_stateTable->state(it).parent) {
                if (it == ancestor)
                    break;
                ++depth;
            }
            return depth;
        };

        const auto &s1 = m_stateTable->transition(t1).source;
        const auto &s2 = m_stateTable->transition(t2).source;
        if (s1 == s2) {
            return t1 < t2;
        } else if (isDescendant(s1, s2)) {
            return true;
        } else if (isDescendant(s2, s1)) {
            return false;
        } else {
            const int lcca = findLCCA({ s1, s2 });
            const int s1Depth = descendantDepth(s1, lcca);
            const int s2Depth = descendantDepth(s2, lcca);
            if (s1Depth == s2Depth)
                return s1 < s2;
            else
                return s1Depth > s2Depth;
        }
    });

    OrderedSet filteredTransitions;
    for (int t1 : sortedTransitions) {
        OrderedSet transitionsToRemove;
        bool t1Preempted = false;
        OrderedSet exitSetT1;
        computeExitSet({t1}, exitSetT1);
        const int source1 = m_stateTable->transition(t1).source;
        for (int t2 : filteredTransitions) {
            OrderedSet exitSetT2;
            computeExitSet({t2}, exitSetT2);
            if (exitSetT1.intersectsWith(exitSetT2)) {
                const int source2 = m_stateTable->transition(t2).source;
                if (isDescendant(source1, source2)) {
                    transitionsToRemove.add(t2);
                } else {
                    t1Preempted = true;
                    break;
                }
            }
        }
        if (!t1Preempted) {
            for (int t3 : transitionsToRemove) {
                filteredTransitions.remove(t3);
            }
            filteredTransitions.add(t1);
        }
    }
    *enabledTransitions = filteredTransitions;
}

void QScxmlStateMachinePrivate::getProperAncestors(std::vector<int> *ancestors, int state1,
                                                   int state2) const
{
    Q_ASSERT(ancestors);

    if (state1 == -1) {
        return;
    }

    int parent = state1;
    do {
        parent = m_stateTable->state(parent).parent;
        if (parent == state2) {
            break;
        }
        ancestors->push_back(parent);
    } while (parent != -1);
}

void QScxmlStateMachinePrivate::microstep(const OrderedSet &enabledTransitions)
{
    if (qscxmlLog().isDebugEnabled()) {
        qCDebug(qscxmlLog) << q_func()
                           << "starting microstep, configuration:"
                           << stateNames(m_configuration.list());
        qCDebug(qscxmlLog) << q_func() << "enabled transitions:";
        for (int t : enabledTransitions) {
            const auto &transition = m_stateTable->transition(t);
            QString from = QStringLiteral("(none)");
            if (transition.source != StateTable::InvalidIndex)
                from = m_tableData->string(m_stateTable->state(transition.source).name);
            QStringList to;
            if (transition.targets == StateTable::InvalidIndex) {
                to.append(QStringLiteral("(none)"));
            } else {
                for (int t : m_stateTable->array(transition.targets))
                    to.append(m_tableData->string(m_stateTable->state(t).name));
            }
            qCDebug(qscxmlLog) << q_func() << "\t" << t << ":" << from << "->"
                               << to.join(QLatin1Char(','));
        }
    }

    exitStates(enabledTransitions);
    executeTransitionContent(enabledTransitions);
    enterStates(enabledTransitions);

    qCDebug(qscxmlLog) << q_func() << "finished microstep, configuration:"
                       << stateNames(m_configuration.list());
}

void QScxmlStateMachinePrivate::exitStates(const OrderedSet &enabledTransitions)
{
    OrderedSet statesToExit;
    computeExitSet(enabledTransitions, statesToExit);
    auto statesToExitSorted = statesToExit.takeList();
    std::sort(statesToExitSorted.begin(), statesToExitSorted.end(), std::greater<int>());
    qCDebug(qscxmlLog) << q_func() << "exiting states" << stateNames(statesToExitSorted);
    for (int s : statesToExitSorted) {
        const auto &state = m_stateTable->state(s);
        if (state.serviceFactoryIds != StateTable::InvalidIndex)
            m_statesToInvoke.remove(s);
    }
    for (int s : statesToExitSorted) {
        for (int h : historyStates(s)) {
            const auto &hState = m_stateTable->state(h);
            QVector<int> history;

            for (int s0 : m_configuration) {
                const auto &s0State = m_stateTable->state(s0);
                if (hState.type == StateTable::State::DeepHistory) {
                    if (s0State.isAtomic() && isDescendant(s0, s))
                        history.append(s0);
                } else {
                    if (s0State.parent == s)
                        history.append(s0);
                }
            }

            m_historyValue[h] = history;
        }
    }
    for (int s : statesToExitSorted) {
        const auto &state = m_stateTable->state(s);
        if (state.exitInstructions != StateTable::InvalidIndex)
            m_executionEngine->execute(state.exitInstructions);
        m_configuration.remove(s);
        emitStateActive(s, false);
        removeService(s);
    }

    if (m_infoSignalProxy) {
        emit m_infoSignalProxy->statesExited(
                QVector<QScxmlStateMachineInfo::StateId>(statesToExitSorted.begin(),
                                                         statesToExitSorted.end()));
    }
}

void QScxmlStateMachinePrivate::computeExitSet(const OrderedSet &enabledTransitions,
                                               OrderedSet &statesToExit) const
{
    for (int t : enabledTransitions) {
        const auto &transition = m_stateTable->transition(t);
        if (transition.targets == StateTable::InvalidIndex) {
            // nothing to do here: there is no exit set
        } else {
            const int domain = getTransitionDomain(t);
            for (int s : m_configuration) {
                if (isDescendant(s, domain))
                    statesToExit.add(s);
            }
        }
    }
}

void QScxmlStateMachinePrivate::executeTransitionContent(const OrderedSet &enabledTransitions)
{
    for (int t : enabledTransitions) {
        const auto &transition = m_stateTable->transition(t);
        if (transition.transitionInstructions != StateTable::InvalidIndex)
            m_executionEngine->execute(transition.transitionInstructions);
    }

    if (m_infoSignalProxy) {
        emit m_infoSignalProxy->transitionsTriggered(
                QVector<QScxmlStateMachineInfo::TransitionId>(enabledTransitions.list().begin(),
                                                              enabledTransitions.list().end()));
    }
}

void QScxmlStateMachinePrivate::enterStates(const OrderedSet &enabledTransitions)
{
    Q_Q(QScxmlStateMachine);

    OrderedSet statesToEnter, statesForDefaultEntry;
    HistoryContent defaultHistoryContent;
    computeEntrySet(enabledTransitions, &statesToEnter, &statesForDefaultEntry,
                    &defaultHistoryContent);
    auto sortedStates = statesToEnter.takeList();
    std::sort(sortedStates.begin(), sortedStates.end());
    qCDebug(qscxmlLog) << q_func() << "entering states" << stateNames(sortedStates);
    for (int s : sortedStates) {
        const auto &state = m_stateTable->state(s);
        m_configuration.add(s);
        if (state.serviceFactoryIds != StateTable::InvalidIndex)
            m_statesToInvoke.insert(s);
        if (m_stateTable->binding == StateTable::LateBinding && m_isFirstStateEntry[s]) {
            if (state.initInstructions != StateTable::InvalidIndex)
                m_executionEngine->execute(state.initInstructions);
            m_isFirstStateEntry[s] = false;
        }
        if (state.entryInstructions != StateTable::InvalidIndex)
            m_executionEngine->execute(state.entryInstructions);
        if (statesForDefaultEntry.contains(s)) {
            const auto &initialTransition = m_stateTable->transition(state.initialTransition);
            if (initialTransition.transitionInstructions != StateTable::InvalidIndex)
                m_executionEngine->execute(initialTransition.transitionInstructions);
        }
        const int dhc = defaultHistoryContent.value(s);
        if (dhc != StateTable::InvalidIndex)
            m_executionEngine->execute(dhc);
        if (state.type == StateTable::State::Final) {
            if (state.parentIsScxmlElement()) {
                bool running = isRunnable() && !isPaused();
                m_runningState = Finished;
                if (running)
                    emit q->runningChanged(false);
            } else {
                const auto &parent = m_stateTable->state(state.parent);
                m_executionEngine->execute(state.doneData, m_tableData->string(parent.name));
                if (parent.parent != StateTable::InvalidIndex) {
                    const auto &grandParent = m_stateTable->state(parent.parent);
                    if (grandParent.isParallel()) {
                        if (allInFinalStates(getChildStates(grandParent))) {
                            auto e = new QScxmlEvent;
                            e->setEventType(QScxmlEvent::InternalEvent);
                            e->setName(QStringLiteral("done.state.")
                                       + m_tableData->string(grandParent.name));
                            q->submitEvent(e);
                        }
                    }
                }
            }
        }
    }
    for (int s : sortedStates)
        emitStateActive(s, true);
    if (m_infoSignalProxy) {
        emit m_infoSignalProxy->statesEntered(
                QVector<QScxmlStateMachineInfo::StateId>(sortedStates.begin(),
                                                         sortedStates.end()));
    }
}

void QScxmlStateMachinePrivate::computeEntrySet(const OrderedSet &enabledTransitions,
                                                OrderedSet *statesToEnter,
                                                OrderedSet *statesForDefaultEntry,
                                                HistoryContent *defaultHistoryContent) const
{
    Q_ASSERT(statesToEnter);
    Q_ASSERT(statesForDefaultEntry);
    Q_ASSERT(defaultHistoryContent);

    for (int t : enabledTransitions) {
        const auto &transition = m_stateTable->transition(t);
        if (transition.targets == StateTable::InvalidIndex)
            // targetless transition, so nothing to do
            continue;
        for (int s : m_stateTable->array(transition.targets))
            addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry,
                                       defaultHistoryContent);
        auto ancestor = getTransitionDomain(t);
        OrderedSet targets;
        getEffectiveTargetStates(&targets, t);
        for (auto s : targets)
            addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry,
                                     defaultHistoryContent);
    }
}

void QScxmlStateMachinePrivate::addDescendantStatesToEnter(
        int stateIndex, OrderedSet *statesToEnter, OrderedSet *statesForDefaultEntry,
        HistoryContent *defaultHistoryContent) const
{
    Q_ASSERT(statesToEnter);
    Q_ASSERT(statesForDefaultEntry);
    Q_ASSERT(defaultHistoryContent);

    const auto &state = m_stateTable->state(stateIndex);
    if (state.isHistoryState()) {
        HistoryValues::const_iterator historyValueIter = m_historyValue.find(stateIndex);
        if (historyValueIter != m_historyValue.end()) {
            auto historyValue = historyValueIter.value();
            for (int s : historyValue)
                addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry,
                                           defaultHistoryContent);
            for (int s : historyValue)
                addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry,
                                         defaultHistoryContent);
        } else {
            const auto transitionIdx = m_stateTable->array(state.transitions)[0];
            const auto &defaultHistoryTransition = m_stateTable->transition(transitionIdx);
            defaultHistoryContent->operator[](state.parent) =
                    defaultHistoryTransition.transitionInstructions;
            StateTable::Array targetStates = m_stateTable->array(defaultHistoryTransition.targets);
            for (int s : targetStates)
                addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry,
                                           defaultHistoryContent);
            for (int s : targetStates)
                addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry,
                                         defaultHistoryContent);
        }
    } else {
        statesToEnter->add(stateIndex);
        if (state.isCompound()) {
            statesForDefaultEntry->add(stateIndex);
            if (state.initialTransition != StateTable::InvalidIndex) {
                auto initialTransition = m_stateTable->transition(state.initialTransition);
                auto initialTransitionTargets = m_stateTable->array(initialTransition.targets);
                for (int targetStateIndex : initialTransitionTargets)
                    addDescendantStatesToEnter(targetStateIndex, statesToEnter,
                                               statesForDefaultEntry, defaultHistoryContent);
                for (int targetStateIndex : initialTransitionTargets)
                    addAncestorStatesToEnter(targetStateIndex, stateIndex, statesToEnter,
                                             statesForDefaultEntry, defaultHistoryContent);
            }
        } else {
            if (state.isParallel()) {
                for (int child : getChildStates(state)) {
                    if (!hasDescendant(*statesToEnter, child))
                        addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry,
                                                   defaultHistoryContent);
                }
            }
        }
    }
}

void QScxmlStateMachinePrivate::addAncestorStatesToEnter(
        int stateIndex, int ancestorIndex, OrderedSet *statesToEnter,
        OrderedSet *statesForDefaultEntry, HistoryContent *defaultHistoryContent) const
{
    Q_ASSERT(statesToEnter);
    Q_ASSERT(statesForDefaultEntry);
    Q_ASSERT(defaultHistoryContent);

    std::vector<int> ancestors;
    getProperAncestors(&ancestors, stateIndex, ancestorIndex);
    for (int anc : ancestors) {
        if (anc == -1) {
            // we can't enter the state machine itself, so:
            continue;
        }
        statesToEnter->add(anc);
        const auto &ancState = m_stateTable->state(anc);
        if (ancState.isParallel()) {
            for (int child : getChildStates(ancState)) {
                if (!hasDescendant(*statesToEnter, child))
                    addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry,
                                               defaultHistoryContent);
            }
        }
    }
}

std::vector<int> QScxmlStateMachinePrivate::getChildStates(
        const QScxmlExecutableContent::StateTable::State &state) const
{
    std::vector<int> childStates;
    auto kids = m_stateTable->array(state.childStates);
    if (kids.isValid()) {
        childStates.reserve(kids.size());
        for (int kiddo : kids) {
            switch (m_stateTable->state(kiddo).type) {
            case StateTable::State::Normal:
            case StateTable::State::Final:
            case StateTable::State::Parallel:
                childStates.push_back(kiddo);
                break;
            default:
                break;
            }
        }
    }
    return childStates;
}

bool QScxmlStateMachinePrivate::hasDescendant(const OrderedSet &statesToEnter, int childIdx) const
{
    for (int s : statesToEnter) {
        if (isDescendant(s, childIdx))
            return true;
    }
    return false;
}

bool QScxmlStateMachinePrivate::allDescendants(const OrderedSet &statesToEnter, int childdx) const
{
    for (int s : statesToEnter) {
        if (!isDescendant(s, childdx))
            return false;
    }
    return true;
}

bool QScxmlStateMachinePrivate::isDescendant(int state1, int state2) const
{
    int parent = state1;
    do {
        parent = m_stateTable->state(parent).parent;
        if (parent == state2)
            return true;
    } while (parent != -1);
    return false;
}

bool QScxmlStateMachinePrivate::allInFinalStates(const std::vector<int> &states) const
{
    if (states.empty())
        return false;

    for (int idx : states) {
        if (!isInFinalState(idx))
            return false;
    }

    return true;
}

bool QScxmlStateMachinePrivate::someInFinalStates(const std::vector<int> &states) const
{
    for (int stateIndex : states) {
        const auto &state = m_stateTable->state(stateIndex);
        if (state.type == StateTable::State::Final && m_configuration.contains(stateIndex))
            return true;
    }
    return false;
}

bool QScxmlStateMachinePrivate::isInFinalState(int stateIndex) const
{
    const auto &state = m_stateTable->state(stateIndex);
    if (state.isCompound())
        return someInFinalStates(getChildStates(state)) && m_configuration.contains(stateIndex);
    else if (state.isParallel())
        return allInFinalStates(getChildStates(state));
    else
        return false;
}

int QScxmlStateMachinePrivate::getTransitionDomain(int transitionIndex) const
{
    const auto &transition = m_stateTable->transition(transitionIndex);
    if (transition.source == -1)
        //oooh, we have the initial transition of the state machine.
        return -1;

    OrderedSet tstates;
    getEffectiveTargetStates(&tstates, transitionIndex);
    if (tstates.isEmpty()) {
        return StateTable::InvalidIndex;
    } else {
        const auto &sourceState = m_stateTable->state(transition.source);
        if (transition.type == StateTable::Transition::Internal
                && sourceState.isCompound()
                && allDescendants(tstates, transition.source)) {
            return transition.source;
        } else {
            tstates.add(transition.source);
            return findLCCA(std::move(tstates));
        }
    }
}

int QScxmlStateMachinePrivate::findLCCA(OrderedSet &&states) const
{
    std::vector<int> ancestors;
    const int head = *states.begin();
    OrderedSet tail(std::move(states));
    tail.removeHead();

    getProperAncestors(&ancestors, head, StateTable::InvalidIndex);
    for (int anc : ancestors) {
        if (anc != -1) { // the state machine itself is always compound
            const auto &ancState = m_stateTable->state(anc);
            if (!ancState.isCompound())
                continue;
        }

        if (allDescendants(tail, anc))
            return anc;
    }

    return StateTable::InvalidIndex;
}

void QScxmlStateMachinePrivate::getEffectiveTargetStates(OrderedSet *targets,
                                                         int transitionIndex) const
{
    Q_ASSERT(targets);

    const auto &transition = m_stateTable->transition(transitionIndex);
    for (int s : m_stateTable->array(transition.targets)) {
        const auto &state = m_stateTable->state(s);
        if (state.isHistoryState()) {
            HistoryValues::const_iterator historyValueIter = m_historyValue.find(s);
            if (historyValueIter != m_historyValue.end()) {
                for (int historyState : historyValueIter.value()) {
                    targets->add(historyState);
                }
            } else {
                getEffectiveTargetStates(targets, m_stateTable->array(state.transitions)[0]);
            }
        } else {
            targets->add(s);
        }
    }
}

/*!
 * Creates a state machine from the SCXML file specified by \a fileName.
 *
 * This method will always return a state machine. If errors occur while reading the SCXML file,
 * the state machine cannot be started. The errors can be retrieved by calling the parseErrors()
 * method.
 *
 * \sa parseErrors()
 */
QScxmlStateMachine *QScxmlStateMachine::fromFile(const QString &fileName)
{
    QFile scxmlFile(fileName);
    if (!scxmlFile.open(QIODevice::ReadOnly)) {
        auto stateMachine = new QScxmlStateMachine(&QScxmlStateMachine::staticMetaObject);
        QScxmlError err(scxmlFile.fileName(), 0, 0, QStringLiteral("cannot open for reading"));
        QScxmlStateMachinePrivate::get(stateMachine)->parserData()->m_errors.append(err);
        return stateMachine;
    }

    QScxmlStateMachine *stateMachine = fromData(&scxmlFile, fileName);
    scxmlFile.close();
    return stateMachine;
}

/*!
 * Creates a state machine by reading from the QIODevice specified by \a data.
 *
 * This method will always return a state machine. If errors occur while reading the SCXML file,
 * \a fileName, the state machine cannot be started. The errors can be retrieved by calling the
 * parseErrors() method.
 *
 * \sa parseErrors()
 */
QScxmlStateMachine *QScxmlStateMachine::fromData(QIODevice *data, const QString &fileName)
{
    QXmlStreamReader xmlReader(data);
    QScxmlCompiler compiler(&xmlReader);
    compiler.setFileName(fileName);
    return compiler.compile();
}

QVector<QScxmlError> QScxmlStateMachine::parseErrors() const
{
    Q_D(const QScxmlStateMachine);
    return d->m_parserData ? d->m_parserData->m_errors : QVector<QScxmlError>();
}

QScxmlStateMachine::QScxmlStateMachine(const QMetaObject *metaObject, QObject *parent)
    : QObject(*new QScxmlStateMachinePrivate(metaObject), parent)
{
    Q_D(QScxmlStateMachine);
    d->m_executionEngine = new QScxmlExecutionEngine(this);
}

QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *parent)
    : QObject(dd, parent)
{
    Q_D(QScxmlStateMachine);
    d->m_executionEngine = new QScxmlExecutionEngine(this);
}

/*!
    \property QScxmlStateMachine::running

    \brief the running state of this state machine

    \sa start()
 */

/*!
    \qmlproperty bool ScxmlStateMachine::running

    The running state of this state machine.
*/

/*!
    \property QScxmlStateMachine::dataModel

    \brief The data model to be used for this state machine.

    SCXML data models are described in
    \l {SCXML Specification - 5 Data Model and Data Manipulation}. For more
    information about supported data models, see \l {SCXML Compliance}.

    Changing the data model when the state machine has been \c initialized is
    not specified in the SCXML standard and leads to undefined behavior.

    \sa QScxmlDataModel, QScxmlNullDataModel, QScxmlEcmaScriptDataModel,
        QScxmlCppDataModel
*/

/*!
    \qmlproperty ScxmlDataModel ScxmlStateMachine::dataModel

    The data model to be used for this state machine.

    SCXML data models are described in
    \l {SCXML Specification - 5 Data Model and Data Manipulation}. For more
    information about supported data models, see \l {SCXML Compliance}.

    Changing the data model when the state machine has been \l initialized is
    not specified in the SCXML standard and leads to undefined behavior.

    \sa QScxmlDataModel, QScxmlNullDataModel, QScxmlEcmaScriptDataModel,
        QScxmlCppDataModel
*/

/*!
    \property QScxmlStateMachine::initialized

    \brief Whether the state machine has been initialized.

    It is \c true if the state machine has been initialized, \c false otherwise.

    \sa QScxmlStateMachine::init(), QScxmlDataModel
*/

/*!
    \qmlproperty bool ScxmlStateMachine::initialized

    This read-only property is set to \c true if the state machine has been
    initialized, \c false otherwise.
*/

/*!
    \property QScxmlStateMachine::initialValues

    \brief The initial values to be used for setting up the data model.

    \sa QScxmlStateMachine::init(), QScxmlDataModel
*/

/*!
    \qmlproperty var ScxmlStateMachine::initialValues

    The initial values to be used for setting up the data model.
*/

/*!
    \property QScxmlStateMachine::sessionId

    \brief The session ID of the current state machine.

    The session ID is used for message routing between parent and child state machines. If a state
    machine is started by an \c <invoke> element, any event it sends will have the \c invokeid field
    set to the session ID. The state machine will use the origin of an event (which is set by the
    \e target or \e targetexpr attribute in a \c <send> element) to dispatch messages to the correct
    child state machine.

    \sa QScxmlEvent::invokeId()
 */

/*!
    \qmlproperty string ScxmlStateMachine::sessionId

    The session ID of the current state machine.

    The session ID is used for message routing between parent and child state
    machines. If a state machine is started by an \c <invoke> element, any event
    it sends will have the \c invokeid field set to the session ID. The state
    machine will use the origin of an event (which is set by the \e target or
    \e targetexpr attribute in a \c <send> element) to dispatch messages to the
    correct child state machine.
*/

/*!
    \property QScxmlStateMachine::name

    \brief The name of the state machine as set by the \e name attribute of the \c <scxml> tag.
 */

/*!
    \qmlproperty string ScxmlStateMachine::name

    The name of the state machine as set by the \e name attribute of the
    \c <scxml> tag.
*/

/*!
    \property QScxmlStateMachine::invoked

    \brief Whether the state machine was invoked from an outer state machine.

    \c true when the state machine was started as a service with the \c <invoke> element,
    \c false otherwise.
 */

/*!
    \qmlproperty bool ScxmlStateMachine::invoked

    Whether the state machine was invoked from an outer state machine.

    This read-only property is set to \c true when the state machine was started
    as a service with the \c <invoke> element, \c false otherwise.
 */

/*!
    \property QScxmlStateMachine::parseErrors

    \brief The list of parse errors that occurred while creating a state machine from an SCXML file.
 */

/*!
    \qmlproperty var ScxmlStateMachine::parseErrors

    The list of parse errors that occurred while creating a state machine from
    an SCXML file.
 */

/*!
    \property QScxmlStateMachine::loader

    \brief The loader that is currently used to resolve and load URIs for the state machine.
 */

/*!
    \qmlproperty Loader ScxmlStateMachine::loader

    The loader that is currently used to resolve and load URIs for the state
    machine.
 */

/*!
    \property QScxmlStateMachine::tableData

    \brief The table data that is used when generating C++ from an SCXML file.

    The class implementing
    the state machine will use this property to assign the generated table
    data. The state machine does not assume ownership of the table data.
 */

QString QScxmlStateMachine::sessionId() const
{
    Q_D(const QScxmlStateMachine);

    return d->m_sessionId;
}

QString QScxmlStateMachinePrivate::generateSessionId(const QString &prefix)
{
    int id = ++QScxmlStateMachinePrivate::m_sessionIdCounter;
    return prefix + QString::number(id);
}

bool QScxmlStateMachine::isInvoked() const
{
    Q_D(const QScxmlStateMachine);
    return d->m_isInvoked;
}

bool QScxmlStateMachine::isInitialized() const
{
    Q_D(const QScxmlStateMachine);
    return d->m_isInitialized;
}

/*!
 * Sets the data model for this state machine to \a model. There is a 1:1
 * relation between state machines and models. After setting the model once you
 * cannot change it anymore. Any further attempts to set the model using this
 * method will be ignored.
 */
void QScxmlStateMachine::setDataModel(QScxmlDataModel *model)
{
    Q_D(QScxmlStateMachine);

    if (d->m_dataModel == nullptr && model != nullptr) {
        d->m_dataModel = model;
        if (model)
            model->setStateMachine(this);
        emit dataModelChanged(model);
    }
}

/*!
 * Returns the data model used by the state machine.
 */
QScxmlDataModel *QScxmlStateMachine::dataModel() const
{
    Q_D(const QScxmlStateMachine);

    return d->m_dataModel;
}

void QScxmlStateMachine::setLoader(QScxmlCompiler::Loader *loader)
{
    Q_D(QScxmlStateMachine);

    if (loader != d->m_loader) {
        d->m_loader = loader;
        emit loaderChanged(loader);
    }
}

QScxmlCompiler::Loader *QScxmlStateMachine::loader() const
{
    Q_D(const QScxmlStateMachine);

    return d->m_loader;
}

QScxmlTableData *QScxmlStateMachine::tableData() const
{
    Q_D(const QScxmlStateMachine);

    return d->m_tableData;
}

void QScxmlStateMachine::setTableData(QScxmlTableData *tableData)
{
    Q_D(QScxmlStateMachine);

    if (d->m_tableData == tableData)
        return;

    d->m_tableData = tableData;
    if (tableData) {
        d->m_stateTable = reinterpret_cast<const QScxmlExecutableContent::StateTable *>(
                    tableData->stateMachineTable());
        if (objectName().isEmpty()) {
            setObjectName(tableData->name());
        }
        if (d->m_stateTable->maxServiceId != QScxmlExecutableContent::StateTable::InvalidIndex) {
            const size_t serviceCount = size_t(d->m_stateTable->maxServiceId + 1);
            d->m_invokedServices.resize(serviceCount, { -1, nullptr, QString() });
            d->m_cachedFactories.resize(serviceCount, nullptr);
        }

        if (d->m_stateTable->version != Q_QSCXMLC_OUTPUT_REVISION) {
           qFatal("Cannot mix incompatible state table (version 0x%x) with this library "
                  "(version 0x%x)", d->m_stateTable->version, Q_QSCXMLC_OUTPUT_REVISION);
        }
        Q_ASSERT(tableData->stateMachineTable()[d->m_stateTable->arrayOffset +
                                                d->m_stateTable->arraySize]
                == QScxmlExecutableContent::StateTable::terminator);
    }

    d->updateMetaCache();

    emit tableDataChanged(tableData);
}

/*!
    \qmlmethod ScxmlStateMachine::stateNames(bool compress)

    Retrieves a list of state names of all states.

    When \a compress is \c true (the default), the states that contain child
    states is filtered out and only the \e {leaf states} is returned.  When it
    is \c false, the full list of all states is returned.

    The returned list does not contain the states of possible nested state
    machines.

    \note The order of the state names in the list is the order in which the
    states occurred in the SCXML document.
*/

/*!
 * Retrieves a list of state names of all states.
 *
 * When \a compress is \c true (the default), the states that contain child states
 * will be filtered out and only the \e {leaf states} will be returned.
 * When it is \c false, the full list of all states will be returned.
 *
 * The returned list does not contain the states of possible nested state machines.
 *
 * \note The order of the state names in the list is the order in which the states occurred in
 *       the SCXML document.
 */
QStringList QScxmlStateMachine::stateNames(bool compress) const
{
    Q_D(const QScxmlStateMachine);

    QStringList names;
    for (int i = 0; i < d->m_stateTable->stateCount; ++i) {
        const auto &state = d->m_stateTable->state(i);
        if (!compress || state.isAtomic())
            names.append(d->m_tableData->string(state.name));
    }
    return names;
}

/*!
    \qmlmethod ScxmlStateMachine::activeStateNames(bool compress)

    Retrieves a list of state names of all active states.

    When a state is active, all its parent states are active by definition. When
    \a compress is \c true (the default), the parent states are filtered out and
    only the \e {leaf states} are returned. When it is \c false, the full list
    of active states is returned.
*/

/*!
 * Retrieves a list of state names of all active states.
 *
 * When a state is active, all its parent states are active by definition. When \a compress
 * is \c true (the default), the parent states will be filtered out and only the \e {leaf states}
 * will be returned. When it is \c false, the full list of active states will be returned.
 */
QStringList QScxmlStateMachine::activeStateNames(bool compress) const
{
    Q_D(const QScxmlStateMachine);

    QStringList result;
    for (int stateIdx : d->m_configuration) {
        const auto &state = d->m_stateTable->state(stateIdx);
        if (state.isAtomic() || !compress)
            result.append(d->m_tableData->string(state.name));
    }
    return result;
}

/*!
    \qmlmethod ScxmlStateMachine::isActive(string scxmlStateName)

    Returns \c true if the state specified by \a scxmlStateName is active,
    \c false otherwise.
*/

/*!
 * Returns \c true if the state specified by \a scxmlStateName is active, \c false otherwise.
 */
bool QScxmlStateMachine::isActive(const QString &scxmlStateName) const
{
    Q_D(const QScxmlStateMachine);

    for (int stateIndex : d->m_configuration) {
        const auto &state = d->m_stateTable->state(stateIndex);
        if (d->m_tableData->string(state.name) == scxmlStateName)
            return true;
    }

    return false;
}

QMetaObject::Connection QScxmlStateMachine::connectToStateImpl(const QString &scxmlStateName,
                                                               const QObject *receiver, void **slot,
                                                               QtPrivate::QSlotObjectBase *slotObj,
                                                               Qt::ConnectionType type)
{
    const int *types = nullptr;
    if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
        types = QtPrivate::ConnectionTypes<QtPrivate::List<bool> >::types();

    Q_D(QScxmlStateMachine);
    const int signalIndex = d->m_stateNameToSignalIndex.value(scxmlStateName, -1);
    return signalIndex < 0 ? QMetaObject::Connection()
                           : QObjectPrivate::connectImpl(this, signalIndex, receiver, slot, slotObj,
                                                         type, types, d->m_metaObject);
}

/*!
    Creates a connection of the given \a type from the state identified by \a scxmlStateName
    to the \a method in the \a receiver object. The receiver's \a method
    may take a boolean argument that indicates whether the state connected
    became active or inactive. For example:

    \code
    void mySlot(bool active);
    \endcode

    Returns a handle to the connection, which can be used later to disconnect.
 */
QMetaObject::Connection QScxmlStateMachine::connectToState(const QString &scxmlStateName,
                                                           const QObject *receiver,
                                                           const char *method,
                                                           Qt::ConnectionType type)
{
    QByteArray signalName = QByteArray::number(QSIGNAL_CODE) + scxmlStateName.toUtf8()
            + "Changed(bool)";
    return QObject::connect(this, signalName.constData(), receiver, method, type);
}

/*!
    Creates a connection of the specified \a type from the event specified by
    \a scxmlEventSpec to the \a method in the \a receiver object. The receiver's
    \a method may take a QScxmlEvent as a parameter. For example:

    \code
    void mySlot(const QScxmlEvent &event);
    \endcode

    In contrast to event specifications in SCXML documents, spaces are not
    allowed in the \a scxmlEventSpec here. In order to connect to multiple
    events with different prefixes, connectToEvent() has to be called multiple
    times.

    Returns a handle to the connection, which can be used later to disconnect.
*/
QMetaObject::Connection QScxmlStateMachine::connectToEvent(const QString &scxmlEventSpec,
                                                           const QObject *receiver,
                                                           const char *method,
                                                           Qt::ConnectionType type)
{
    Q_D(QScxmlStateMachine);
    return d->m_router.connectToEvent(scxmlEventSpec.split(QLatin1Char('.')), receiver, method,
                                      type);
}

QMetaObject::Connection QScxmlStateMachine::connectToEventImpl(const QString &scxmlEventSpec,
                                                               const QObject *receiver, void **slot,
                                                               QtPrivate::QSlotObjectBase *slotObj,
                                                               Qt::ConnectionType type)
{
    Q_D(QScxmlStateMachine);
    return d->m_router.connectToEvent(scxmlEventSpec.split(QLatin1Char('.')), receiver, slot,
                                      slotObj, type);
}

/*!
    \qmlmethod ScxmlStateMachine::init()

    Initializes the state machine by setting the initial values for \c <data>
    elements and executing any \c <script> tags of the \c <scxml> tag. The
    initial data values are taken from the \l initialValues property.

    Returns \c false if parse errors occur or if any of the initialization steps
    fail. Returns \c true otherwise.
*/

/*!
 * Initializes the state machine.
 *
 * State machine initialization consists of calling QScxmlDataModel::setup(), setting the initial
 * values for \c <data> elements, and executing any \c <script> tags of the \c <scxml> tag. The
 * initial data values are taken from the \c initialValues property.
 *
 * Returns \c false if parse errors occur or if any of the initialization steps fail.
 * Returns \c true otherwise.
 */
bool QScxmlStateMachine::init()
{
    Q_D(QScxmlStateMachine);

    if (d->m_isInitialized)
        return false;

    if (!parseErrors().isEmpty())
        return false;

    if (!dataModel() || !dataModel()->setup(d->m_initialValues))
        return false;

    if (!d->executeInitialSetup())
        return false;

    d->m_isInitialized = true;
    emit initializedChanged(true);
    return true;
}

/*!
 * Returns \c true if the state machine is running, \c false otherwise.
 *
 * \sa setRunning(), runningChanged()
 */
bool QScxmlStateMachine::isRunning() const
{
    Q_D(const QScxmlStateMachine);

    return d->isRunnable() && !d->isPaused();
}

/*!
 * Starts the state machine if \a running is \c true, or stops it otherwise.
 *
 * \sa start(), stop(), isRunning(), runningChanged()
 */
void QScxmlStateMachine::setRunning(bool running)
{
    if (running)
        start();
    else
        stop();
}

QVariantMap QScxmlStateMachine::initialValues()
{
    Q_D(const QScxmlStateMachine);
    return d->m_initialValues;
}

void QScxmlStateMachine::setInitialValues(const QVariantMap &initialValues)
{
    Q_D(QScxmlStateMachine);
    if (initialValues != d->m_initialValues) {
        d->m_initialValues = initialValues;
        emit initialValuesChanged(initialValues);
    }
}

QString QScxmlStateMachine::name() const
{
    return tableData()->name();
}

/*!
    \qmlmethod ScxmlStateMachine::submitEvent(event)

    Submits the SCXML event \a event to the internal or external event queue
    depending on the priority of the event.

    When a delay is set, the event will be queued for delivery after the timeout
    has passed. The state machine takes ownership of the event and deletes it
    after processing.

    \sa QScxmlEvent
 */

/*!
 * Submits the SCXML event \a event to the internal or external event queue depending on the
 * priority of the event.
 *
 * When a delay is set, the event will be queued for delivery after the timeout has passed.
 * The state machine takes ownership of \a event and deletes it after processing.
 */
void QScxmlStateMachine::submitEvent(QScxmlEvent *event)
{
    Q_D(QScxmlStateMachine);

    if (!event)
        return;

    if (event->delay() > 0) {
        qCDebug(qscxmlLog) << this << "submitting event" << event->name()
                           << "with delay" << event->delay() << "ms:"
                           << QScxmlEventPrivate::debugString(event).constData();

        Q_ASSERT(event->eventType() == QScxmlEvent::ExternalEvent);
        d->submitDelayedEvent(event);
    } else {
        qCDebug(qscxmlLog) << this << "submitting event" << event->name()
                           << ":" << QScxmlEventPrivate::debugString(event).constData();

        d->routeEvent(event);
    }
}

/*!
 * A utility method to create and submit an external event with the specified
 * \a eventName as the name.
 */
void QScxmlStateMachine::submitEvent(const QString &eventName)
{
    QScxmlEvent *e = new QScxmlEvent;
    e->setName(eventName);
    e->setEventType(QScxmlEvent::ExternalEvent);
    submitEvent(e);
}
/*!
    \qmlmethod ScxmlStateMachine::submitEvent(string eventName, var data)

    A utility method to create and submit an external event with the specified
    \a eventName as the name and \a data as the payload data (optional).
*/

/*!
 * A utility method to create and submit an external event with the specified
 * \a eventName as the name and \a data as the payload data.
 */
void QScxmlStateMachine::submitEvent(const QString &eventName, const QVariant &data)
{
    QScxmlEvent *e = new QScxmlEvent;
    e->setName(eventName);
    e->setEventType(QScxmlEvent::ExternalEvent);
    e->setData(data);
    submitEvent(e);
}

/*!
    \qmlmethod ScxmlStateMachine::cancelDelayedEvent(string sendId)

    Cancels a delayed event with the specified \a sendId.
*/

/*!
 * Cancels a delayed event with the specified \a sendId.
 */
void QScxmlStateMachine::cancelDelayedEvent(const QString &sendId)
{
    Q_D(QScxmlStateMachine);

    for (auto it = d->m_delayedEvents.begin(), eit = d->m_delayedEvents.end(); it != eit; ++it) {
        if (it->second->sendId() == sendId) {
            qCDebug(qscxmlLog) << this
                               << "canceling event" << sendId
                               << "with timer id" << it->first;
            d->m_eventLoopHook.killTimer(it->first);
            delete it->second;
            d->m_delayedEvents.erase(it);
            return;
        }
    }
}

/*!
    \qmlmethod ScxmlStateMachine::isDispatchableTarget(string target)

    Returns \c true if a message to \a target can be dispatched by this state
    machine.

    Valid targets are:
    \list
    \li \c #_parent for the parent state machine if the current state machine
        is started by \c <invoke>
    \li \c #_internal for the current state machine
    \li \c #_scxml_sessionid, where \c sessionid is the session ID of the
        current state machine
    \li \c #_servicename, where \c servicename is the ID or name of a service
        started with \c <invoke> by this state machine
    \endlist
 */

/*!
 * Returns \c true if a message to \a target can be dispatched by this state machine.
 *
 * Valid targets are:
 * \list
 * \li  \c #_parent for the parent state machine if the current state machine is started by
 *      \c <invoke>
 * \li  \c #_internal for the current state machine
 * \li  \c #_scxml_sessionid, where \c sessionid is the session ID of the current state machine
 * \li  \c #_servicename, where \c servicename is the ID or name of a service started with
 *      \c <invoke> by this state machine
 * \endlist
 */
bool QScxmlStateMachine::isDispatchableTarget(const QString &target) const
{
    Q_D(const QScxmlStateMachine);

    if (isInvoked() && target == QStringLiteral("#_parent"))
        return true; // parent state machine, if we're <invoke>d.
    if (target == QStringLiteral("#_internal")
            || target == QStringLiteral("#_scxml_%1").arg(sessionId()))
        return true; // that's the current state machine

    if (target.startsWith(QStringLiteral("#_"))) {
        QStringRef targetId = target.midRef(2);
        for (auto invokedService : d->m_invokedServices) {
            if (invokedService.service && invokedService.service->id() == targetId)
                return true;
        }
    }

    return false;
}

/*!
    \qmlproperty list ScxmlStateMachine::invokedServices

    A list of SCXML services that were invoked from the main state machine
    (possibly recursively).
*/

/*!
    \property QScxmlStateMachine::invokedServices
    \brief A list of SCXML services that were invoked from the main
    state machine (possibly recursively).
*/

QVector<QScxmlInvokableService *> QScxmlStateMachine::invokedServices() const
{
    Q_D(const QScxmlStateMachine);

    QVector<QScxmlInvokableService *> result;
    for (int i = 0, ei = int(d->m_invokedServices.size()); i != ei; ++i) {
        if (auto service = d->m_invokedServices[size_t(i)].service)
            result.append(service);
    }
    return result;
}

/*!
  \fn QScxmlStateMachine::runningChanged(bool running)

  This signal is emitted when the \c running property is changed with \a running as argument.
*/

/*!
  \fn QScxmlStateMachine::log(const QString &label, const QString &msg)

  This signal is emitted if a \c <log> tag is used in the SCXML. \a label is the value of the
  \e label attribute of the \c <log> tag. \a msg is the value of the evaluated \e expr attribute
  of the \c <log> tag. If there is no \e expr attribute, a null string will be returned.
*/

/*!
    \qmlsignal ScxmlStateMachine::log(string label, string msg)

    This signal is emitted if a \c <log> tag is used in the SCXML. \a label is
    the value of the \e label attribute of the \c <log> tag. \a msg is the value
    of the evaluated \e expr attribute of the \c <log> tag. If there is no
    \e expr attribute, a null string will be returned.

    The corresponding signal handler is \c onLog().
*/

/*!
  \fn QScxmlStateMachine::reachedStableState()

  This signal is emitted when the event queue is empty at the end of a macro step or when a final
  state is reached.
*/

/*!
    \qmlsignal ScxmlStateMachine::reachedStableState()

    This signal is emitted when the event queue is empty at the end of a macro
    step or when a final state is reached.

    The corresponding signal handler is \c onreachedStableState().
*/

/*!
  \fn QScxmlStateMachine::finished()

  This signal is emitted when the state machine reaches a top-level final state.

  \sa running
*/

/*!
    \qmlsignal ScxmlStateMachine::finished()

    This signal is emitted when the state machine reaches a top-level final
    state.

    The corresponding signal handler is \c onFinished().
*/

/*!
    \qmlmethod ScxmlStateMachine::start()

    Starts this state machine. The machine resets its configuration and
    transitions to the initial state. When a final top-level state
    is entered, the machine emits the finished() signal.

    \sa stop(), finished()
*/

/*!
  Starts this state machine. The machine will reset its configuration and
  transition to the initial state. When a final top-level state
  is entered, the machine will emit the finished() signal.

  \note A state machine will not run without a running event loop, such as
  the main application event loop started with QCoreApplication::exec() or
  QApplication::exec().

  \sa runningChanged(), setRunning(), stop(), finished()
*/
void QScxmlStateMachine::start()
{
    Q_D(QScxmlStateMachine);

    if (!parseErrors().isEmpty())
        return;

    // Failure to initialize doesn't prevent start(). See w3c-ecma/test487 in the scion test suite.
    if (!isInitialized() && !init())
        qCDebug(qscxmlLog) << this << "cannot be initialized on start(). Starting anyway ...";

    d->start();
    d->m_eventLoopHook.queueProcessEvents();
}

/*!
    \qmlmethod ScxmlStateMachine::stop()

    Stops this state machine. The machine will not execute any further state
    transitions. Its \l running property is set to \c false.

    \sa start(), finished()
*/

/*!
  Stops this state machine. The machine will not execute any further state
  transitions. Its \c running property is set to \c false.

  \sa runningChanged(), start(), setRunning()
 */
void QScxmlStateMachine::stop()
{
    Q_D(QScxmlStateMachine);
    d->pause();
}

/*!
  Returns \c true if the state with the ID \a stateIndex is active.

  This method is part of the interface to the compiled representation of SCXML
  state machines. It should only be used internally and by state machines
  compiled from SCXML documents.
 */
bool QScxmlStateMachine::isActive(int stateIndex) const
{
    Q_D(const QScxmlStateMachine);
    return d->m_configuration.contains(stateIndex);
}

QT_END_NAMESPACE
