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

#include "ActionViewerAPI.h"

#include <Viewer.h>
#include <Action.h>
#include <Component.h>

#include <QWidget>
#include <QComboBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>
#include <QStackedWidget>
#include <QCompleter>
#include <QLineEdit>

namespace camitk {
class PropertyObject;
}

/**
 * @ingroup group_sdk_libraries_core_actionviewer
 *
 * @brief
 * ActionViewer is the viewer used to manage the actions.
 *
 * By default all action widgets are displayed in this viewer widget (in the QStackedWidget).
 * There is also a search panel to find an action to apply to the currently selected component.
 * The search panel is shown by default. Use setSearchPanelVisible(false) to hide it.
 *
 * \note
 * This is a very special viewer as it calls setComponentClassNames(...) method with an empty list.
 * This means that this viewer is going to be notified/refreshed every time the
 * current selected action is changed (i.e., anytime an action is triggered).
 *
 * Use Application::getViewer("Action Viewer") to get the default instance of this viewer.
 *
 * @see camitk::Action
 */
class ACTIONVIEWER_API ActionViewer : public camitk::Viewer {
    Q_OBJECT

public:
    /** @name General
      */
    ///@{
    /// constructor
    Q_INVOKABLE ActionViewer(QString name);

    /// destructor
    virtual ~ActionViewer();

    /// @name Inherited from Viewer
    //@{
    /// refresh the view (can be interesting to know which other viewer is calling this)
    virtual void refresh(Viewer* whoIsAsking = nullptr) override;

    /// get the viewer widget
    virtual QWidget* getWidget() override;

    /// get the  InteractiveViewer propertyObject (only non-null for GEOMETRY_VIEWER)
    camitk::PropertyObject* getPropertyObject() override;

    /// get the explorer menu
    QMenu* getMenu() override;
    //@}

    /// show/hide the search panel (visible by default)
    void setSearchPanelVisible(bool);
    //@}

protected slots :
    /// Method used to change the action selected
    void changeName();

    /// Method used to change the action family selected
    void changeFamily();

    /// Method used to change the tag
    void changeTag();

private:
    /// Enum the different fields of the action viewwer
    enum UpdateReason {ActionFamilyChanged, ActionNameChanged, ActionTagChanged, ViewerRefresh};

    /// @name Specific to the Action viewer
    //@{
    /// embed an action widget in the stacked widget if needed
    virtual void updateActionWidget(camitk::Action*);

    /// method used to update the viewer for a given update field
    void updateSearchPanel(UpdateReason);

    /// Main action widget of the viewer
    QWidget* myWidget;

    /// Family combo box
    QComboBox* familyComboBox;

    /// Action name combo box
    QComboBox* nameComboBox;

    /// Current action
    camitk::Action* action;

    /// action tags line edit
    QLineEdit* tagLineEdit;

    /// actions stacked widget of the viewer
    QStackedWidget* actionWidgetStack;

    /// the search panel
    QFrame* searchFramePanel;

    /// the QMenu for the viewer (View -> Action Viewer)
    QMenu* myMenu;

    /// index of the empty widget, used when no action is active or when no action has been used for the currently selected components
    int emptyActionWidgetIndex;

    /// this map stores the list of selected component and the corresponding stack index of their embedded action
    QMap<camitk::ComponentList, camitk::Action*> widgetHistory;

    /// Used to evaluate modification of the list while execution
    camitk::ComponentList currentlySelected;


    /**
      * @name CamiTK Properties of this viewer
      */
    ///@{
    /// The property object that holds the properties of this viewer
    camitk::PropertyObject* propertyObject;

    /**
     * Event filter of this class instance to watch its properties instances.
     * Each time a property is dynamically changed, this method is called.
     *
     * @note Only used by Geometry viewers
     */
    bool eventFilter(QObject* object, QEvent* event) override;

    ///@}
};

#endif // ACTIONVIEWER_H
