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

//-- Specific action stuffs
#include "PlaneWidget.h"

//-- Core stuffs
#include <Action.h>
#include <MeshComponent.h>

// VTK stuffs
#include <vtkSmartPointer.h>
#include <vtkPlane.h>

/**
 * This action allows the user to clip several kinds of MeshComponents : vtkStructuredGridClip,  vtkUnstructuredGridClip, vtkPolyData.
 *
 * This action allows 2 clipping modes :
 * - Only selected meshes are clipped
 * - All the opened meshes are clipped
 * The switch between those 2 approaches can easily be processed thanks to the related button in the action viewer.
 *
 * This action uses a vtkImplicitPlaneWidget which can be either hidden or visible thanks to the related button in the action viewer.
 *
 * This action can also restore the clipped meshes to their former "unclipped" state thanks to the restore Meshes button.
 * Basically, when you're done using the clipping tool, you can, for example, restore the initial unclipped meshes and hide the plane
 * before switching to another action.
 *
 * Saving a clipped component can be done by clicking the dedicated button.
 *
 * \note When a component is added/deleted, the action needs to be refreshed in order to take the modifications into account.
 * This can easily be done by clicking the update button.
 *
 */
class MeshClipping : public camitk::Action {
    Q_OBJECT

public:
    /// The constructor.
    MeshClipping(camitk::ActionExtension*);

    /// The destructor.
    virtual ~MeshClipping();

    /// Method called when the action when the action is triggered (i.e. started).
    virtual QWidget* getWidget();

public slots:
    /// Method called when the action is applied.
    virtual camitk::Action::ApplyStatus apply();

    /// specific slot called when the mesh currently clipped is deleted
    virtual void meshDeleted();

private:
    /** Customizes the action viewer.
     *  (i.e remove apply and revert buttons and adds the 4 specific buttons for meshclipping action).
     */
    void customizeActionLayout();

    /// Clips the mesh throughout the plane specified and return the ApplyStatus
    ApplyStatus clipMesh(camitk::MeshComponent* mesh, vtkSmartPointer<vtkPlane> plane);

    /// List of MeshComponent that are currently targeted by the clipping.
    camitk::ComponentList currentlyClippedMeshes;

    /// Class which contains the widget (implements vtkCommand).
    PlaneWidget* widget;

    /// Controls smooth or chiselled (raw) clipping.
    bool smoothing;

    /// Controls which components are clipped : all opened components or only selected components.
    bool allComponents;

    /// Controls the clipping widget visibility.
    bool planeVisibility;

    /// Controls the saving of the clipped component.
    bool save;

    /// Contains the clipping widget bounding box [xmin, xmax, ymin, ymax, zmin, zmax].
    double limBounds[6];

private slots:

    /// Method called when the update button is clicked
    /// re-calculates the widget box size when new components are added or deleted
    /// (i.e increases or decreases the box size according to the scene bounds).
    void updateBox();

    /// Method called when the restore button is clicked.
    void restoreMeshes();

    /// Method called when the clip all components button is clicked.
    void changeAllComponents();

    /// Method called when the smooth button is clicked.
    void changeSmoothing();

    /// Method called when the visibility button is clicked.
    void changeVisibility();

    /// Method called when the saving button is clicked.
    void saveClippedMeshes();

private:
    /// update the dimension of the vtk plane widget
    /// @param refreshViewer refresh all the application viewers only if this is true
    void updateBox(bool refreshViewer);

};

#endif // MESH_CLIPPING_H
