/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/


#ifndef ACTIONSTATEMACHINE_H
#define ACTIONSTATEMACHINE_H


// -- Qt stuff
#include <QTextStream>
#include <QStateMachine>
#include <QState>
#include <QFinalState>
#include <QDir>

// -- Qt XML stuff
#include <QtXml/QDomDocument>
#include <QtXml/QDomNodeList>

// -- CamiTK Core stuff
#include <Application.h>

// -- CamiTK Local stuff
#include "ActionState.h"
#include "SaveActionState.h"

/**
 * @ingroup group_sdk_application_asm
 *
 * @brief
 * This Class describes ActionStateMachine MainWindow extension.
 * This application use a modified version of SCXML that describes a pipeline of CamiTK actions.
 *
 */
class ActionStateMachine : public camitk::Application {
    Q_OBJECT

public:
    /** construtor.
     *  This method may throw an AbortException if a problem occurs.
     */
    ActionStateMachine(int& argc, char** argv, QString inputFileName = "", QString outputDirectory = "");

    /// destructor
    virtual ~ActionStateMachine() = default;

    /// where to save the files
    QString getSaveDirectory();

public slots:
    /// Automatically loop to apply to next state for all states
    void autoNext();

private slots:
    /// finish everything properly when the state machine entered the final state and quit
    void finished();

protected:
    /// initialized main window
    void initMainWindow();

    /** check that the file is a SCXML file (simple checking, no XML Schema validation yet)
     *  This method may throw an AbortException if a problem occurs.
     */
    void checkSCXMLFile(QString filename);

    /** parse the XML file (using Qt DOM API)
     *  This method may throw an AbortException if a problem occurs.
     */
    QString parseSCXMLTree();

    ///@name Attributes
    ///@{

    /// Application's name
    QString name;

    /// Actual state machine
    QStateMachine machine;

    ///  main window
    camitk::MainWindow* mainWindow;

    /// XML tree containing infos
    QDomDocument scxmlDoc;

    /// Map of action state to build transitions
    QMap<QString, ActionState*> statesMap;

    /// Final State
    QFinalState* finalState;

    /// Where to save all files
    QDir saveDirectory;

    /// To get track of the Action State Machine the duration
    QTime stateMachineTimer;

    /// Log stream to write report on logFile
    QTextStream* logStream;

    /// Log file
    QFile* logFile;

    ///@}

private:
    /// @name Tool methods used, see parseSCXMLTree()
    /// @{

    /// This method may throw an AbortException if a problem occurs.
    void createAllActionStates(QDomNodeList nodeList);

    /// This method may throw an AbortException if a problem occurs.
    void createTransitions(QDomNodeList nodeList);

    /// This method may throw an AbortException if a problem occurs.
    void setCamiTKAction(ActionState* actionState, QDomElement actionElement);

    /// This method may throw an AbortException if a problem occurs.
    void setCamiTKSaveAction(SaveActionState* actionState, QDomElement actionElement);

    QVector<camitk::Action::ApplyStatus> stringToStatus(QString listOfStatus);
    ///@}

    /// build a specific error message containing the line and column if available
    QString getDomNodeLocation(QDomNode);
};

#endif // ACTIONSTATEMACHINE_H
