//=========================================================================
//  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.
//=========================================================================

#ifndef vtk_aeva_ext_vtkGlobalIdBooleans_h
#define vtk_aeva_ext_vtkGlobalIdBooleans_h

#include "vtk/aeva/ext/AEVAExtModule.h"
#include "vtkUnstructuredGridAlgorithm.h"

// These exist because Microsoft sometimes stupidly defines them:
#ifdef Boolean
#undef Boolean
#endif
#ifdef UNION
#undef UNION
#endif
#ifdef INTERSECTION
#undef INTERSECTION
#endif
#ifdef DIFFERENCE
#undef DIFFERENCE
#endif

class vtkDataSet;

/**\brief Perform a boolean cell-selection operation by global ID.
  *
  * This filter takes 2 input data objects (a tool and workpiece).
  * It selects cells from the workpiece based on their presence in
  * or absence from the tool, based on the operation specified.
  * The cells are identified solely by global ID, so if IDs are
  * missing from either data object, the filter fails with an error.
  */
class AEVAEXT_EXPORT vtkGlobalIdBooleans : public vtkUnstructuredGridAlgorithm
{
public:
  static vtkGlobalIdBooleans* New();
  vtkTypeMacro(vtkGlobalIdBooleans, vtkUnstructuredGridAlgorithm);
  void PrintSelf(std::ostream& os, vtkIndent indent) override;

  enum Boolean
  {
    UNION,
    INTERSECTION,
    DIFFERENCE
  };
  /// Set/get how to choose workpiece cells relative to the tool's cells.
  vtkSetMacro(Operation, int);
  vtkGetMacro(Operation, int);
  virtual void SetOperationToUnion() { this->SetOperation(UNION); }
  virtual void SetOperationToIntersection() { this->SetOperation(INTERSECTION); }
  virtual void SetOperationToDifference() { this->SetOperation(DIFFERENCE); }

  /// Output cells are taken from the workpiece's cells and (for UNION only) the tool's cells.
  virtual void SetWorkpiece(vtkDataObject* obj) { this->SetInputDataObject(0, obj); }
  /// The workpiece cells are modulated by the tool's cells.
  virtual void SetTool(vtkDataObject* obj) { this->SetInputDataObject(1, obj); }

protected:
  vtkGlobalIdBooleans();
  ~vtkGlobalIdBooleans() override;

  /// Implementation for intersection and difference operations
  int FilterById(vtkDataSet* workpiece, vtkDataSet* tool, vtkDataSet* result);

  int FillInputPortInformation(int port, vtkInformation* info) override;
  int RequestData(vtkInformation* request,
    vtkInformationVector** inInfo,
    vtkInformationVector* outInfo) override;

  int Operation{ UNION };
};

#endif // vtk_aeva_ext_vtkGlobalIdBooleans_h
