/*****************************************************************************
 * $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 ACTIONSTATE_H
#define ACTIONSTATE_H

// Qt stuff
#include <QTime>
#include <QState>
#include <QVector>
#include <QTextStream>

//CamiTK stuff
#include <Action.h>

// Local stuff
#include "ActionStateWidget.h"
#include "ActionTransition.h"
/**
 * @ingroup group_sdk_application_asm
 *
 * @brief
 * The state (in a state machine point of view) corresponding to the current processed action.
 *
 * By default an ActionState is not defined as being the initial state.
 */
class ActionState : public QState {

    Q_OBJECT

public:
    /**
     */
    ActionState(QState* parent, QString name, QString description, QTextStream* logStream = nullptr);

    void setAction(camitk::Action* action,
                   QMap<QString, QVariant> parameters,
                   QMap<QString, QString> inputComponentNames,
                   QMap<QString, QString> outputComponentNames);

    /// Returns the name of the action state (may be different from the name of the actual action)
    QString getName();

    /// Returns the description of the action state (may be different from the description of the actual action)
    QString getDescription();

    /// May change its description according to the previous action result
    void setAlternativeDesc(QString altDescText, QVector<camitk::Action::ApplyStatus> statusList);

    /// apply the action encapsulated by this action state
    virtual camitk::Action::ApplyStatus applyAction();

    /// Adds a possible transition from this action
    ActionTransition* addActionTransition(QString transitionName, QAbstractState* nextState,
                                          bool applyAction = true, QVector<camitk::Action::ApplyStatus> disableConditions = QVector<camitk::Action::ApplyStatus>());

    // get the whole action state widget (used by the ActionStateViewer)
    ActionStateWidget* getWidget();

    // set the status of previous action and modify description/possible action accordingly
    void setPreviousActionStatus(camitk::Action::ApplyStatus status);

    /// get the names and type of all input components
    const QMap<QString, QString>& getInputComponents();

    /// get the names and type of all output components
    const QMap<QString, QString>& getOutputComponents();

    /// programmatically call the onEntry() method (used during autonext)
    void autoNextEntry();

    /// programmatically call the onExit() method (used during autonext)
    void autoNextExit();

protected:
    /// Reimplemented from QState
    /// @{
    void onEntry(QEvent* event) override;

    void onExit(QEvent* event) override;
    ///@}

    /// Name of the state action (may not be the same as the action's name)
    QString name;

    /** Description of the state action
     *  may not be the same as the action's description but complementary
     */
    QString description;

    /// Actual CamiTK action
    camitk::Action* myAction;

    /// names of all the input compenent, this is a map <name, type>
    QMap<QString, QString> inputComponentNames;

    /// names of all the output compenent, this is a map <name, type>
    QMap<QString, QString> outputComponentNames;

    /// name and value of preset parameters
    QMap<QString, QVariant> parameters;

    /// Buttons that should be disabled if the previous aciton state did not happen correctly
    QMap<camitk::Action::ApplyStatus, QVector<QPushButton* > > conditionalButtons;

    /// Descriptions that should be displaied if the previous action state did not happen correctly
    QMap<camitk::Action::ApplyStatus, QString> conditionalDescriptions;

    /**
     * Widget containing:
     *  - the name of the state action
     *  - the description of the action
     *  - the action's widget
     *  - the buttons linking to the transitions
     */
    ActionStateWidget* myStateWidget;

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

    /// Keep track of time...
    QTime actionTimer;

};
#endif // ACTIONSTATE_H
