/**============================================================================
 *
 * \file   generic_filter.hpp
 * \brief  Apply a filter to an image (generic declarations).
 *
 * \author Leblanc Christophe.
 * \date   11/01/2015
 * \email cleblancad@gmail.com
 *
 * Code inspired from:
 * 'Getting Started with ITK + VTK'
 * L. Ibanez, W. Schroeder, Insight Software Consortium.
 *
 *
 *===========================================================================*/

#ifndef TOMOPROCESS_FILTER_GENERIC_FILTER_HPP
#define TOMOPROCESS_FILTER_GENERIC_FILTER_HPP

#include "filter_definitions.hpp"

TOMOPROCESS_OPEN_GLOBAL_NAMESPACE
TOMOPROCESS_OPEN_FILTER_NAMESPACE

/** \class GenericFilter
  * \brief Apply a filter to an image (generic declarations).
  *
  * GenericFilter<TomoprocessImageType>
  *
  * TomoprocessImageType: type of image from tomoprocess 
  * (e.g. an instance of class Image<InputPixelType, OutputPixelType, Dimension>
  * see 'Image.hpp')
  *
  * Uses ITK.
  *
  * \ingroup Object
  *
  */
template< class ImageT >
class GenericFilter: public Object
{
public:
  //
  // Typedefs.
  //
  
  /// \brief This type.
  typedef GenericFilter 	Self;
  
  /// \brief Parent class.
  typedef Object 		SuperClass;
  
  /// \brief Image type used.
  typedef ImageT 		ImageType;
  
  /// \brief Input image type.
  typedef typename ImageType::InputImageType  InputImageType;
  
  /// \brief Output image type.
  typedef typename ImageType::OutputImageType OutputImageType;
  
  /// \brief Input image pointer type.
  typedef typename ImageType::InputImagePtrType  InputImagePtrType;
  
  /// \brief Output image pointer type.
  typedef typename ImageType::OutputImagePtrType OutputImagePtrType;
  
  /// \brief Pointer object type returned by the filter.
  typedef itk::ProcessObject* ProcessObjectPtrType;
  
  //
  // Functions.
  //
  
  /// \brief Default constructor.
  GenericFilter(std::ostream &os = std::cerr): SuperClass(TOMOPROCESS_FILTER_DEFAULT_CLASS_NAME,
			      TOMOPROCESS_FILTER_DEFAULT_CLASS_DESCRIPTION),
    m_Os(&os)
  {}

  /// \brief Copy constructor.
  /// \param[in] rhs object to copy.
  GenericFilter(const GenericFilter &rhs): SuperClass(rhs) {}
  
  /// \brief Destructor.
  virtual ~GenericFilter() {}
  
  /// \brief Copy operator.
  /// \param[in] rhs object to copy.
  /// \return Copied object.
  virtual GenericFilter& operator=(const GenericFilter &rhs)
  {
    if(this != &rhs) SuperClass::operator=(rhs);
    return *this;
  }
  
  /// \brief Clones the data.
  /// \warning May be memory consuming.
  /// \return Pointer on copied data.
  virtual GenericFilter* Clone() const = 0;
  
  /// \brief Sets the first filter input.
  /// \param[in] inputImage pointer to input image.
  virtual void SetInput(const InputImageType* inputImage) = 0;
  
  /// \brief Sets filter's nth input.
  /// \param[in] n input number.
  /// \param[in] inputImage pointer to input image.
  virtual void SetInput(unsigned int n, const InputImageType* inputImage) = 0;
  
  /// \brief Returns the first filtered image.
  /// \return Output image.
  virtual OutputImageType* GetOutput() = 0;
  
  /// \brief Returns the nth filtered image.
  /// \param[in] n output image number.
  /// \return nth output image.
  virtual OutputImageType* GetOutput(unsigned int n) = 0;
  
  /// \brief Updates the filter.
  virtual void Update() = 0;
  
  /// \brief Resets the pipeline.
  virtual void ResetPipeline() = 0;
  
  /// \brief Gets a pointer on the internal filter.
  /// \return Pointer on the internal filter.
  virtual ProcessObjectPtrType GetFilter() = 0;
  
  /// \brief sets the data release flag on.
  virtual void ReleaseDataFlagOn() = 0;
  
  /// \brief Sets the release data flag off.
  virtual void ReleaseDataFlagOff() = 0;
  
  /// \brief Sets the release data flag.
  /// \param[in] flag flag value.
  virtual void SetReleaseDataFlag(bool flag) = 0;
  
  /// \brief Gets the release data flag.
  /// \return Flag.
  virtual bool GetReleaseDataFlag() const = 0;
  
  /// \brief Sets the verbose mode flag on.
  virtual void SetVerboseOn() = 0;
  
  /// \brief Sets the verbose mode flag off.
  virtual void SetVerboseOff() = 0;
  
  /// \brief Set the verbose mode flag.
  /// \param[in] flag flag value.
  virtual void SetVerbose(bool flag) = 0;
  
  /// \brief Gets the verbose mode flag.
  /// \return Flag.
  virtual bool GetVerbose() const = 0;
  
  /// \brief Sets the draw mode flag on.
  virtual void SetDrawOn() = 0;
  
  /// \brief Sets the draw mode flag off.
  virtual void SetDrawOff() = 0;
  
  /// \brief Sets the draw mode flag.
  /// \param[in] flag flag value.
  virtual void SetDraw(bool flag) = 0;
  
  /// \brief Gets the draw mode flag.
  /// \return Flag.
  virtual bool GetDraw() const = 0;
  
protected:
  std::ostream* m_Os; ///< Output stream for error messages.
};


TOMOPROCESS_CLOSE_FILTER_NAMESPACE
TOMOPROCESS_CLOSE_GLOBAL_NAMESPACE

#endif // TOMOPROCESS_FILTER_GENERIC_FILTER_HPP