//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================

// .NAME vtkCMBTriangleMesher
// .SECTION Description
// This class will mesh a given 2 dimensional polygon
//
// Input: vtkPolyData
//   The input vtkPolyData must have certain properties.
//   It is assumed that all lines form closed polygons.
//   Any polygon that you want to be meshed must be stored
//   as a series of VTK_LINE's with the following properties
//
//   The input vtkPolyData needs to be processed using
//   the vtkCMBPrepareForTriangleMesher class that helps you describe
//   how the poly data will be meshed
//
//   See vtkCMBPrepareForTriangleMesher for how to format the input poly data

#ifndef __smtk_vtk_vtkCMBTriangleMesher_h
#define __smtk_vtk_vtkCMBTriangleMesher_h

#include "smtk/extension/vtk/meshing/Exports.h" // For export macro
#include "vtkPolyDataAlgorithm.h"

class vtkCMBMeshServerLauncher;

class VTKSMTKMESHINGEXT_EXPORT vtkCMBTriangleMesher : public vtkPolyDataAlgorithm
{

public:
  static vtkCMBTriangleMesher* New();
  vtkTypeMacro(vtkCMBTriangleMesher, vtkPolyDataAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;
  // Description:
  // When relativly calculating maximum areas the size of
  // each individual polygon is used when this is true.
  // When false the bounds of all objects are used
  // default: false
  vtkSetMacro(UseUniqueAreas, bool);
  vtkGetMacro(UseUniqueAreas, bool);

  // Description:
  // A way to add points or preserve boundaries of polygons
  // WARNING: This option assume that no boundaries are
  // touching. Things will break if two boundaries of different
  // polygons are in contact.
  // default: true
  vtkSetMacro(PreserveBoundaries, bool);
  vtkGetMacro(PreserveBoundaries, bool);

  // Description:
  // The returned mesh will have elementIds returned with the vtkPolyData
  // for nodes and edges, as well as faces
  vtkSetMacro(PreserveEdgesAndNodes, bool);
  vtkGetMacro(PreserveEdgesAndNodes, bool);

  // Description:
  // A way to absolutely or relativly set the maximum triangle
  // area used by triangle. Whether this is absolute or relative
  // depends on the current configuration
  // default: 1/8
  vtkSetMacro(MaxArea, double);
  vtkGetMacro(MaxArea, double);

  // Description:
  // Get the max area that is sent to triangle. This returns the result
  // of the combination of the MaxArea and the MaxAreaMode.
  vtkGetMacro(ComputedMaxArea, double);

  enum MaxAreaModeOptions
  {
    NoMaxArea,
    AbsoluteArea,
    RelativeToBounds,
    RelativeToBoundsAndSegments
  };
  // Description:
  //This tells triangle how to constrain the maximum area of a
  //triangle
  //0 - No max Area
  //     >No area constraints will generate a very coarse
  //     >mesh. Not advised
  //1 - Use Absolute Area
  //     >Tells triangle to make sure there are no
  //     >triangles generated bigger than MaxArea
  //2 - Use Area Relative to Bounds
  //     >Tells triangle to make sure there are no
  //     >triangles generated  bigger than Bounds * MaxArea
  //3 - Use Area Relative to Bounds And Segments
  //     >Tells triangle to make sure there are no triangles
  //     >generated bigger than (Bounds / NumSegments) * MaxArea
  //default: 3
  vtkSetClampMacro(MaxAreaMode, int, 0, 3);
  vtkGetMacro(MaxAreaMode, int);

  // Description:
  // A way to enable verbose console output from the mesher
  // default: false
  vtkSetMacro(VerboseOutput, bool);
  vtkGetMacro(VerboseOutput, bool);
  vtkBooleanMacro(VerboseOutput, bool);

  // Description:
  // A way to generate the maximum triangle area constraint
  // currently uses 0.01 of the area of the bounds
  // default: false
  vtkSetMacro(UseMinAngle, bool);
  vtkGetMacro(UseMinAngle, bool);
  vtkSetClampMacro(MinAngle, double, 0, VTK_DOUBLE_MAX); //defaults to 20.0
  vtkGetMacro(MinAngle, double);

  // Description:
  // Set/get the mesh server launcher class used to
  // submit data to be triangulated.
  //
  // Initially NULL, this will be set to a non-NULL value (if required),
  // when RequestData() is invoked.
  virtual void SetLauncher(vtkCMBMeshServerLauncher* launcher);
  vtkGetObjectMacro(Launcher, vtkCMBMeshServerLauncher);

protected:
  vtkCMBTriangleMesher();
  ~vtkCMBTriangleMesher();

  //Used to configure triangle's 'q' flag
  double MinAngle;
  bool UseMinAngle;

  //Used to configure triangle's 'Y' flag
  bool PreserveBoundaries;

  //Used to configure triangle's segment markers
  //and point attribute list
  bool PreserveEdgesAndNodes;

  //Used to configure triangle's 'a' flag
  double MaxArea;
  //the actual paramater that is sent to triangle for max area
  double ComputedMaxArea;
  //Can either be
  //0 - No max Area
  //1 - Use Absolute Area
  //2 - Use Area Relative to Bounds
  //3 - Use Area Relative to Bounds And Segments
  int MaxAreaMode;
  bool UseUniqueAreas;

  //Used to configure triangle's 'V' flag
  bool VerboseOutput;

  // Allow the same launcher for multiple meshing operations:
  vtkCMBMeshServerLauncher* Launcher;

  int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;

private:
  vtkCMBTriangleMesher(const vtkCMBTriangleMesher&); // Not implemented.
  void operator=(const vtkCMBTriangleMesher&);       // Not implemented.
};

#endif
