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

#include "ComponentExplorerAPI.h"

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

// -- QT stuff
#include <QTreeWidget>
#include <QTreeWidgetItem>

namespace camitk {
// -- Core stuff classes
class InterfaceNode;
class Component;
class ExplorerItem;
}

/**
 * @ingroup group_sdk_libraries_core_explorer
 *
 * @brief
 * The Component Explorer viewer displays the list of all data currently opened in the application.
 * All objects are displayed in a QListView widget and can be selected
 * (single/multiple selection is available).
 *
 * \image html libraries/explorer.png "The component explorer viewer."
 *
 * It manages the camitk::InterfaceNode facet of components.
 *
 * If this viewer extension is loaded, the default instance of this viewer can be accessed directly
 * by Application::getViewer("Component Explorer").
 *
 * @see camitk::InterfaceNode
 * @see camitk::Viewer
 */
class COMPONENT_EXPLORER_API ComponentExplorer : public camitk::Viewer {
    Q_OBJECT

public:
    /** @name General
      */
    ///@{
    /** Construtor */
    Q_INVOKABLE ComponentExplorer(QString);

    /** Destructor */
    ~ComponentExplorer() override;

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

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

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

    ///@}

public slots :

    /// slot called by the explorer menu when the user wants to rename the currently selected Component
    void renameItem();

private slots :

    /// slot called whenever the selection changed in the explorer
    void explorerSelectionChanged();

    /// slot called when an item was double clicked
    void doubleClicked(QTreeWidgetItem*, int);

    /// slot called on right button click
    void rightButtonPressed(const QPoint&);

private:

    /// @name QTreeWidgetItem/InterfaceNode map
    ///@{
    /// the map to get the Component* from the QTreeWidgetItem*
    QMap<QTreeWidgetItem*, camitk::Component*> itemComponentMap;

    /// the map to get the QTreeWidgetItem corresponding to a parentComp
    QMap<camitk::Component*, QTreeWidgetItem*> topLevelCompItemMap;

    /// Return the QTreeWidgetItem of a given Component (return nullptr if not found)
    QTreeWidgetItem* getItem(camitk::Component*);
    ///@}

    /// @name QTreeWidget and QTreeWidgetItem management
    ///@{
    /// instantiate a new QTreeWidgetItem using names and properties from the InterfaceNode, and using parent
    QTreeWidgetItem* getNewItem(QTreeWidgetItem* parent, camitk::Component*);

    /// recursively add the Component in the tree explorer and return the QTreeWidgetItem of the InterfaceNode
    QTreeWidgetItem* add(QTreeWidgetItem*, camitk::Component*);

    /** Add the given Component to the explorer (at top level) and automatically create children Component items.
     * @param comp The Component to add in the tree view.
     * @param index if given insert at a given position
     */
    void addTopLevel(camitk::Component* comp, int index = -1);

    /// remove a given item from the explorer (return its index in the parent item list)
    void remove(QTreeWidgetItem*);

    /** Remove the Component (its Component and its sub-item) from the explorer list (if present).
     * The Component itself is of course not deleted here.
     */
    void removeTopLevel(camitk::Component* comp);

    /** Update the interface node representation of a given Component, (creates a new sub-item for all the new
      *  sub items and delete all the sub-item which are not sub items any more).
      *  Call this method when the Component has created a new sub-item or when it has removed one of
      *  its sub items.
      *  If the component was not displayed in the explorer, this method does nothing.
     * @param comp The InterfaceNode provider to update list.
     */
    void refreshInterfaceNode(camitk::Component* comp);

    /// the list view
    QTreeWidget* explorerTree;
    ///@}

    /// @name Menu
    ///@{
    /// the QMenu for the explorer
    QMenu* explorerMenu;

    /// the possible action
    QAction* editRename;
    ///@}
};

#endif // COMPONENTEXPLORER_H
