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

#include "PropertyExplorerAPI.h"

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

// -- QT stuff
#include <QtTreePropertyBrowser>
#include <QtButtonPropertyBrowser>
#include <QtGroupBoxPropertyBrowser>

// -- QT stuff classes
class QTabWidget;
class QPushButton;
class QWidget;

namespace camitk {
class ObjectController;
}

/**
 * @ingroup group_sdk_libraries_core_propertyexplorer
 *
 * @brief
 * The property explorer.
 *
 * The property explorer is a special container, placed generally
 * below the explorer. It has a default tab (property editor) and can
 * include any number of other tabs (where you can, of course, have any kind of widgets
 * you want: slider, labels, text, ...).
 *
 * It manages the camitk::InterfaceProperty facet of components.
 *
 * \image html libraries/propertyexplorer.png "The property explorer viewer."
 *
 * The property editor is a "magic" widget (aka as "poOOowerful" widget)
 * that use QObject derived class and build a property editor UI.
 * It is presented as a list (automatically build from your QObject derived class
 * Q_PROPERTY or added CamiTK properties):
 * - first column is the property name,
 * - second column is the editing widgets (where the user can interactively change
 *   the property value).
 *
 * See also ObjectController documentation for more informations and a complete example of the property editor
 *
 * If this viewer extension is loaded, the default instance of this viewer can be accessed directly
 * by Application::getViewer("Property Explorer").
 *
 * @see camitk::Property
 * @see camitk::InterfaceProperty
 * @see camitk::Viewer
 */
class PROPERTYEXPLORER_API PropertyExplorer : public camitk::Viewer {
    Q_OBJECT
    Q_ENUMS(camitk::ObjectController::ViewMode); // so that it can be used in property editor

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

    /// destructor
    ~PropertyExplorer() override;
    ///@}

    /** @name Inherited from Viewer
      */
    ///@{
    /// refresh the property editor
    void refresh(camitk::Viewer* whoIsAsking = nullptr) override;

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

    /// add a property to change the ObjectController representation at run-time (user choice)
    camitk::PropertyObject* getPropertyObject() override;
    ///@}

    ///@name Tab selection management
    ///@{

    /// Select the tab containing the given widget in the PropertyExplorer.
    /// @param widget the PropertyExplorer's widget of the tab to select.
    /// @note the widget must have been previously added to the PropertyExplorer.
    void selectWidget(QWidget* widget);

    /// Select the tab of the given index in the PropertyExplorer.
    /// @param index the index of the tab to display.
    /// @note 0 <= index < currentComponent->getNumberOfPropertyWidget() else nothing is done
    void selectIndex(unsigned int index);

    ///@}


private:

    /// the widgets
    camitk::ObjectController* theController;
    QTabWidget* tabWidget;
    QPushButton* revertButton;
    QPushButton* applyButton;

    /// the viewed Component
    camitk::Component* currentComponent;

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

    /**
     * The CamiTK property that stands for the ObjectController view mode.
     */
    camitk::Property* viewModeProperty;

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

    /**
     * Create and handle the CamiTK properties of this viewer.
     */
    void createProperties();

    ///@}

    /** clear all the additional widgets, reset currentComponent (and update its visibility).
      * \note this method does not delete the different widgets that were included in the tabs, the Component should do it.
      */
    void clear();

private slots:

    /**
     *  Update the PropertyExplorer tab index to display for the currently selected component
     *  This method is used by the PropertyExplorer to tell for each component which tab has been selected for display.
     *  @param index The index of the PropertyExplorer tab to display for the currently selected component.
     **/
    void updateTabIndexToDisplay(int index);

};

#endif
