/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageAlgorithm.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm 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.

=========================================================================*/
/**
 * @class   vtkImageAlgorithm
 * @brief   Generic algorithm superclass for image algs
 *
 * vtkImageAlgorithm is a filter superclass that hides much of the
 * pipeline complexity. It handles breaking the pipeline execution
 * into smaller extents so that the vtkImageData limits are observed. It
 * also provides support for multithreading. If you don't need any of this
 * functionality, consider using vtkSimpleImageToImageFilter instead.
 * @sa
 * vtkSimpleImageToImageFilter
 */

#ifndef vtkImageAlgorithm_h
#define vtkImageAlgorithm_h

#include "vtkAlgorithm.h"
#include "vtkCommonExecutionModelModule.h" // For export macro

class vtkDataSet;
class vtkImageData;

class VTKCOMMONEXECUTIONMODEL_EXPORT vtkImageAlgorithm : public vtkAlgorithm
{
public:
  vtkTypeMacro(vtkImageAlgorithm, vtkAlgorithm);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  ///@{
  /**
   * Get the output data object for a port on this algorithm.
   */
  vtkImageData* GetOutput();
  vtkImageData* GetOutput(int);
  virtual void SetOutput(vtkDataObject* d);
  ///@}

  /**
   * Process a request from the executive.  For vtkImageAlgorithm, the
   * request will be delegated to one of the following methods: RequestData,
   * RequestInformation, or RequestUpdateExtent.
   */
  vtkTypeBool ProcessRequest(
    vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;

  ///@{
  /**
   * Assign a data object as input. Note that this method does not
   * establish a pipeline connection. Use SetInputConnection to
   * setup a pipeline connection.
   */
  void SetInputData(vtkDataObject*);
  void SetInputData(int, vtkDataObject*);
  ///@}

  ///@{
  /**
   * Get a data object for one of the input port connections.  The use
   * of this method is strongly discouraged, but some filters that were
   * written a long time ago still use this method.
   */
  vtkDataObject* GetInput(int port);
  vtkDataObject* GetInput() { return this->GetInput(0); }
  vtkImageData* GetImageDataInput(int port);
  ///@}

  ///@{
  /**
   * Assign a data object as input. Note that this method does not
   * establish a pipeline connection. Use SetInputConnection to
   * setup a pipeline connection.
   */
  virtual void AddInputData(vtkDataObject*);
  virtual void AddInputData(int, vtkDataObject*);
  ///@}

protected:
  vtkImageAlgorithm();
  ~vtkImageAlgorithm() override;

  /**
   * Subclasses can reimplement this method to collect information
   * from their inputs and set information for their outputs.
   */
  virtual int RequestInformation(vtkInformation* request, vtkInformationVector** inputVector,
    vtkInformationVector* outputVector);

  /**
   * Subclasses can reimplement this method to translate the update
   * extent requests from each output port into update extent requests
   * for the input connections.
   */
  virtual int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*);

  /**
   * Convenience method to copy the scalar type and number of components
   * from the input data to the output data.  You will generally want to
   * call this from inside your RequestInformation method, unless you
   * want the output data to have a different scalar type or number of
   * components from the input.
   */
  virtual void CopyInputArrayAttributesToOutput(vtkInformation* request,
    vtkInformationVector** inputVector, vtkInformationVector* outputVector);

  /**
   * This is called in response to a REQUEST_DATA request from the
   * executive.  Subclasses should override either this method or the
   * ExecuteDataWithInformation method in order to generate data for
   * their outputs.  For images, the output arrays will already be
   * allocated, so all that is necessary is to fill in the voxel values.
   */
  virtual int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
    vtkInformationVector* outputVector);

  /**
   * This is a convenience method that is implemented in many subclasses
   * instead of RequestData.  It is called by RequestData.
   */
  virtual void ExecuteDataWithInformation(vtkDataObject* output, vtkInformation* outInfo);

  ///@{
  /**
   * This method is the old style execute method, provided for the sake
   * of backwards compatibility with older filters and readers.
   */
  virtual void ExecuteData(vtkDataObject* output);
  virtual void Execute();
  ///@}

  ///@{
  /**
   * Allocate the output data.  This will be called before RequestData,
   * it is not necessary for subclasses to call this method themselves.
   */
  virtual void AllocateOutputData(vtkImageData* out, vtkInformation* outInfo, int* uExtent);
  virtual vtkImageData* AllocateOutputData(vtkDataObject* out, vtkInformation* outInfo);
  ///@}

  /**
   * Copy the other point and cell data.  Subclasses will almost never
   * need to reimplement this method.
   */
  virtual void CopyAttributeData(
    vtkImageData* in, vtkImageData* out, vtkInformationVector** inputVector);

  ///@{
  /**
   * These method should be reimplemented by subclasses that have
   * more than a single input or single output.
   * See vtkAlgorithm for more information.
   */
  int FillOutputPortInformation(int port, vtkInformation* info) override;
  int FillInputPortInformation(int port, vtkInformation* info) override;
  ///@}

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

#endif
