// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
/**
 * @class   vtkExtrusionMapper
 * @brief   Mapper for showing datasets with extrusion along the normal.
 *
 * This mapper displays the geometry of a mesh by extruding the points along
 * the direction of the cell normals according a cell-data array. If input mesh
 * is made of squares, the result will be show a "city-map" where every cell
 * is displayed as a building of height depending the cell-data array.
 * When input is a point data, the representation is similar to a height field
 * representation.
 *
 * The direction of extrusion is based on the triangles normals.
 *
 * @par Thanks:
 * This class was written by Joachim Pouderoux and Michael Migliore, Kitware 2017
 * This work was supported by the German Climate Computing Center (DKRZ).
 *
 * @sa
 * vtkCompositePolyDataMapper
 *
 */

#ifndef vtkExtrusionMapper_h
#define vtkExtrusionMapper_h

#include "vtkCompositePolyDataMapper.h"
#include "vtkEmbossingRepresentationsModule.h" // for export macro

class vtkMultiProcessController;

class VTKEMBOSSINGREPRESENTATIONS_EXPORT vtkExtrusionMapper : public vtkCompositePolyDataMapper
{
public:
  static vtkExtrusionMapper* New();
  vtkTypeMacro(vtkExtrusionMapper, vtkCompositePolyDataMapper);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  ///@{
  /**
   * Set/Get the factor used to scale the extrusion. Its value is a percentage,
   * defined according to the maximum length of the bounding box of the mesh.
   * The default value is 50.0, i.e. 50% of the maximum length of the bounding box.
   * Negative values are accepted in order to reverse the direction of extrusion.
   * Default is 50.
   */
  void SetExtrusionFactor(float factor);
  vtkGetMacro(ExtrusionFactor, float);
  ///@}

  ///@{
  /**
   * Set/Get the basis visibility flag. If disabled, the original cell is not drawn.
   * Default is disabeld.
   */
  vtkSetMacro(BasisVisibility, bool);
  vtkGetMacro(BasisVisibility, bool);
  vtkBooleanMacro(BasisVisibility, bool);
  ///@}

  ///@{
  /**
   * Set/Get the auto scaling flag. If disabled, user range is used.
   * Default is enabled.
   */
  vtkSetMacro(AutoScaling, bool);
  vtkGetMacro(AutoScaling, bool);
  vtkBooleanMacro(AutoScaling, bool);
  ///@}

  ///@{
  /**
   * Set/Get the user range.
   * Default is [0,1].
   */
  vtkSetVector2Macro(UserRange, float);
  vtkGetVector2Macro(UserRange, float);
  ///@}

  ///@{
  /**
   * Set/Get the multi process controller object.
   */
  void SetController(vtkMultiProcessController* c);
  vtkGetObjectMacro(Controller, vtkMultiProcessController);
  ///@}

  ///@{
  /**
   * Set/Get the data normalization flag.
   * Default is enabled.
   */
  vtkSetMacro(NormalizeData, bool);
  vtkGetMacro(NormalizeData, bool);
  vtkBooleanMacro(NormalizeData, bool);
  ///@}

  ///@{
  /**
   * Override SetInputArrayToProcess to update data range and save field association.
   */
  using vtkAlgorithm::SetInputArrayToProcess;
  void SetInputArrayToProcess(
    int idx, int port, int connection, int fieldAssociation, const char* name) override;
  void SetInputArrayToProcess(
    int idx, int port, int connection, int fieldAssociation, int fieldAttributeType) override;
  void SetInputArrayToProcess(int idx, vtkInformation* info) override;
  ///@}

  void ResetDataRange();

protected:
  vtkExtrusionMapper();
  ~vtkExtrusionMapper() override;

  /**
   * Creation of a delegator
   */
  vtkCompositePolyDataMapperDelegator* CreateADelegator() override;

  /**
   * Extends bounds to take into account extrusion
   */
  void ComputeBounds() override;

  /**
   * Override to collect global data range in a distributed environment.
   */
  void PreRender(const std::vector<vtkSmartPointer<vtkCompositePolyDataMapperDelegator>>&,
    vtkRenderer*, vtkActor*) override;

  vtkMultiProcessController* Controller = nullptr;
  bool NormalizeData = true;
  int FieldAssociation;
  double LocalDataRange[2];
  double GlobalDataRange[2];

  float ExtrusionFactor = 50.f;
  float MaxBoundsLength = 0.f;
  float UserRange[2];
  bool BasisVisibility = false;
  bool AutoScaling = true;

  friend class vtkOpenGLBatchedExtrusionMapper;

private:
  vtkExtrusionMapper(const vtkExtrusionMapper&) = delete;
  void operator=(const vtkExtrusionMapper&) = delete;
};

#endif
