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

#include "TransformationExplorerAPI.h"

// -- Core stuff
#include <Viewer.h>

// Qt
#include <QTreeWidget>
#include <QPushButton>
#include <QVBoxLayout>

namespace camitk {
// -- Core stuff classes
class FrameOfReference;
class Transformation;
class GraphDisplayWidget;
}

/**
 * @ingroup group_sdk_libraries_core_TransformationExplorer
 *
 * @brief Show a simplified version for the current TransformationManager state
 * with existing transformations and frames.
 * This viewer widget shows
 * - a tree widget with the existing frames
 * - a tree widget with all the transformations that are not composite nor inverse
 * - an interactive graph view that show frames as circles and transformations as arrows
 *
 * @see camitk::TransformationManager
 */
class TRANSFORMATIONEXPLORER_API TransformationExplorer : public camitk::Viewer {
    Q_OBJECT

public:

    /** Constructor */
    Q_INVOKABLE TransformationExplorer(QString);

    /** Destructor */
    virtual ~TransformationExplorer();

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

    /// get the frame explorer widget (QTreeWidget)
    QWidget* getWidget() override;
    ///@}

signals:
    /// signal emitted when the list of Frames was updated
    /// Should be replaced by signals from TransformationManager
    void framesUpdated(QVector<camitk::FrameOfReference*>);

    /// signal emitted when the list of direct Transformations was updated
    /// Should be replaced by signals from TransformationManager
    void directTransformationsUpdated(QVector<camitk::Transformation*>);

    /// signal emitted when the currently selected frame was changed
    /// (the user clicked on a frame in the frame panel)
    void currentFrameChanged(const camitk::FrameOfReference*);

    /// signal emitted when the currently selected transformation was changed
    /// (user clicked on a transformation in the transformation panel)
    void currentTransformationChanged(const camitk::Transformation*);

private:
    // The main widget
    QFrame* mainWidget;

    // Keep the list of frames and transformations to refresh them only if there is a change
    QVector<camitk::FrameOfReference*> currentFrames;
    QVector<camitk::Transformation*> currentDirectTransformations;

    /// @name QTreeWidget and QTreeWidgetItem management
    ///@{

    /** Add the given Transformation to the explorer
     * @param tr The transformation to add
     */
    void addTransformation(const camitk::Transformation* tr, bool addToGraphDisplay = true);

    /**
     * Create a right-click menu for the transformationTree
     */
    void getTransformationMenu(const QPoint& pos);

    /**
     * Create a right-click menu for the frameTree
     */
    void getFrameMenu(const QPoint& pos);

    /** Add the given FrameOfReference to the explorer
     * @param frame The frame to add
     */
    void addFrame(camitk::FrameOfReference* frame, QString componentsNames, QString viewersNames, bool addToGraphDisplay = true);

    // Set the selection in the tree views (called when the graph display signals are triggered)
    void setSelectedFrame(const camitk::FrameOfReference*);
    void setSelectedTransformation(const camitk::Transformation*);

    /// return the UTF-8 character corresponding to n in a circle
    QString circledNumber(int n);

    /// the tree widgets
    QTreeWidget* frameTree;
    QTreeWidget* transformationTree;
    ///@}

    // Graphical view of the transformation graph
    camitk::GraphDisplayWidget* transformationGraphDisplay;
};

#endif
