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

// -- vtk stuff
#include <vtkSmartPointer.h>

// disable warning generated by clang about the surrounded headers
#include "CamiTKDisableWarnings"
#include <vtkProp.h>
#include "CamiTKReEnableWarnings"

#include <QMap>
#include <QString>

// -- vtk stuff Classes
class vtkImageActor;
class vtkActor;
class vtkAxesActor;
class vtkImageData;
class vtkWindowLevelLookupTable;
class vtkTransform;

namespace camitk {
// -- Core stuff Classes
class Component;

/**
 * @ingroup group_sdk_libraries_core_component
 *
 * @brief
 * This class describes what are the methods to implement
 * for a BitMap.
 * An InterfaceBitMap is a kind of simplifier/wrapper for vtkImageData.
 *
 * This class defines an "interface" (in the OOP/java meaning of the term).
 * See the introduction of GoF: "Program to an interface, not an implementation."
 * To see what Erich Gamma has to say about it: http://www.artima.com/lejava/articles/designprinciplesP.html
 * To see what Bjarne Stroustrup has to say about it: http://www.artima.com/intv/modern.html
 *
 * @see Slice
 */

class InterfaceBitMap {

public:

    /// virtual destructor
    virtual ~InterfaceBitMap() = default;

    /// set the original volume image data (the source vtkImageData before any reslice) and refresh the vtk pipeline
    virtual void setOriginalVolume(vtkSmartPointer<vtkImageData>) = 0;

    /** Return the vtkImageActor (vtkProp) representing a slice to be displayed in 2D viewers. */
    virtual vtkSmartPointer<vtkImageActor> get2DImageActor() const = 0;

    /** Return the vtkImageActor (vtkProp) representing a slice to be displayed in 3D viewers. */
    virtual vtkSmartPointer<vtkImageActor> get3DImageActor() const = 0;

    /** Return the vtkActor used to pick pixels in the slices. */
    virtual vtkSmartPointer<vtkActor> getPickPlaneActor() const = 0;

    /** Return the vtkActor used to pick pixels in the slices. */
    virtual vtkSmartPointer<vtkActor> getPixelActor() = 0;

    /** Set the pointer to the image transformation.
     * this should be done once, at initialization, using the frame transformation (getTransform)
     */
    virtual void setArbitraryTransform(vtkSmartPointer<vtkTransform>) = 0;

    /** This method is called when the associated plane has been picked in the InteractiveViewer,
     *  the given coordinates is position where the plane was picked.
     */
    virtual void pixelPicked(double, double, double) = 0;

    /// update the position of the plane surrounding the currently selected slice
    virtual void updatePickPlane() = 0;

    /** Return the number of slices in the image data set. */
    virtual int getNumberOfSlices() const = 0;

    /** Return the index of the current displayed slice. */
    virtual int getSlice() const = 0;

    /** Set the current slice index.
     * If the slice index is less than the first slice index, the first slice is displayed.
     * If the slice index is more than the last slice index, the last slice is displayed.
     * @param s the index of the slice to display (base 0). */
    virtual void setSlice(int s) = 0;

    /// Set the slice corresponding to the given image coordinates (in RAI convention)
    virtual void setSlice(double x, double y, double z) = 0;

    /** Return the number of colors in the images.
     * If color is coded on 1 byte, the images are on 256 grey level.
     * If color is coded on 2 bytes, the images are on 4096 grey level (not 65536). */
    virtual int getNumberOfColors() const = 0;

    /// move the pixel selection green indicator (pixelActor) to the given real position
    virtual void setPixelRealPosition(double, double, double) = 0;

    /** Returns the encapsultaed data structure: the image as a vtkImageData. */
    virtual vtkSmartPointer<vtkImageData> getImageData() const = 0;



    /// @name manage extra prop associated with an InterfaceBitMap
    /// @{
    /// TODO
    /// - put all this management into a dedicated interface
    /// - remove it from InterfaceBitMap and InterfaceGeometry
    /// - remove it from Slice and Geometry helper classes
    /// - create a new associated helper class
    /// - update Component class and all other code using it (if needed)
    /// Note : beware that Geometry requires this to manage to at least "label" and "glyph" extra actors

    /// Return the vtkProp (actors, volumes and annotations) corresponding to the given name
    virtual vtkSmartPointer<vtkProp> getProp(const QString&) = 0;

    /// return the number of additional prop
    virtual unsigned int getNumberOfProp() const = 0;

    /// return an additional prop by its index
    virtual vtkSmartPointer<vtkProp> getProp(unsigned int) = 0;

    /** insert an additional prop, defining it by its name (default visibility = false)
     *  @return true if the additional prop was added (i.e. another additional prop of the same name does not exist)
     */
    virtual bool addProp(const QString&,  vtkSmartPointer<vtkProp>) = 0;

    /** remove a given additional prop.
     * @return true if effictively done
     */
    virtual bool removeProp(const QString&) = 0;
    /// @}

};

}

#endif
