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

#include "CamiTKAPI.h"

#include <QObject>

namespace camitk {
class Property;

/**
 * @ingroup group_sdk_libraries_core_component
 *
 * @brief
 * This class describes what are the methods to implement in order to manage dynamic properties.
 * InterfaceProperty is one of the interfaces implemented by the @ref camitk::Component "Component" class.
 */
class InterfaceProperty : public QObject {
    Q_OBJECT
public:
    /// empty virtual destructor, to avoid memory leak
    ~InterfaceProperty() = default;

    /// Get the inheritance hierachy of this Component instance as a list of QString
    virtual QStringList getHierarchy() const = 0;

    /** Assert that a Component instance really inherits from a given className
     *  @param className the name of the class to compare to
     */
    virtual bool isInstanceOf(QString className) const = 0;

    /** Get a Property given its name
     *  @param name the property name
     *  @return nullptr if the name does not match any property name
     *
     *  @see Property
     */
    Q_INVOKABLE virtual camitk::Property* getProperty(QString name) = 0;

    /** Add a new CamiTK property to the component.
     * If the property already exist, it will just change its value.
     *
     * \note
     * The component takes ownership of the Property instance.
     *
     * @return false if the Qt Meta Object property was added by this method (otherwise the property was already defined and true is returned if it was successfully updated)
     */
    virtual bool addProperty(Property*) = 0;

    /// get the property QVariant (same as property(const char*)) but check if it exists first.
    /// If the property was not declared using addProperty, this methods prints an error message
    /// and returns an invalid QVariant
    virtual QVariant getPropertyValue(const QString& name) const = 0;

    /// set the property QVariant value (same as setProperty(const char*, newValue)) but check if it exists first.
    /// If the property was not declared using addProperty, this methods prints an error message
    /// and returns false
    virtual bool setPropertyValue(const QString& name, QVariant newValue) = 0;

    /**
     * get the number of alternative property widgets
     * @see PropertyExplorer
     */
    virtual unsigned int getNumberOfPropertyWidget() = 0;

    /**
     * get the ith alternative property widget
     * override this method and use the method setObjectName of
     * QWidget if you want alternative widgets
     * @see PropertyExplorer
     */
    virtual QWidget* getPropertyWidgetAt(unsigned int i) = 0;

    /** get the property object that could be understood by PropertyEditor.
     *  Returns this as any Component instance can manage its list of dynamic properties (and Component inherits
     *  from InterfaceProperty aka QObject).
     *  You can also have a separate class to manage your Component properties. In this case, just override this
     *  method and return the corresponding instance.
     *  @see PropertyExplorer
     *  @see ObjectController
     */
    virtual QObject* getPropertyObject() = 0;
    virtual const QObject* getPropertyObject() const = 0;

    /** This method is called when a dynamic property value has been modified.
     * If you override this method, do not forget to call the superclass method
     * for the properties not managed locally in order to properly manage all inherited dynamic properties.
     * This method is called when a dynamic property has been updated.
     *
     * Use getPropertyValue(name) to get the current (updated) value of the dynamic property.
     *
     * @param name the name of the dynamic property
     */
    virtual void propertyValueChanged(QString name) = 0;

    /**
    * Set the index of the tab in the PropertyExplorer to select for display.
    * The PropertyExplorer may feature several tabs of widget.
    * This method allows one to select the tab to display in a given context.
    * @param index the index to select in the tab of the PropertyExplorer.
    **/
    virtual void setIndexOfPropertyExplorerTab(unsigned int index) = 0;

    /**
     * Get the index of the tab in the PropertyExplorer to select for display.
     * The PropertyExplorer may feature several tabs of widget.
     * This method allows one to get the selected tab to display in a given context.
     * @return the index to select in the tab of the PropertyExplorer.
     **/
    virtual unsigned int getIndexOfPropertyExplorerTab() = 0;
};

}

#endif // INTERFACEPROPERTY_H
