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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

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

#ifndef mitkImageTimeSelector_h
#define mitkImageTimeSelector_h

#include <mitkSubImageSelector.h>
#include <MitkCoreExports.h>

namespace mitk
{
  /**
   * \brief Provides access to a volume at a specific time step of the input image.
   *
   * If the input is generated by a ProcessObject, only the required data is
   * requested. The time step and channel can be selected via the corresponding
   * setter methods.
   *
   * \ingroup Process
   * \sa SubImageSelector
   * \sa ImageChannelSelector
   * \sa ImageSliceSelector
   * \sa SelectImageByTimeStep
   * \sa SelectImageByTimePoint
   */
  class MITKCORE_EXPORT ImageTimeSelector : public SubImageSelector
  {
  public:
    mitkClassMacro(ImageTimeSelector, SubImageSelector);

    itkFactorylessNewMacro(Self);

    itkCloneMacro(Self);

    /** \brief Get the time step number to extract. */
    itkGetConstMacro(TimeNr, int);
    /** \brief Set the time step number to extract. */
    itkSetMacro(TimeNr, int);

    /** \brief Get the channel number to extract. */
    itkGetConstMacro(ChannelNr, int);
    /** \brief Set the channel number to extract. */
    itkSetMacro(ChannelNr, int);

  protected:
    ImageTimeSelector();

    ~ImageTimeSelector() override;

    /** \brief Initialize output information (geometry, pixel type, dimensions) for the 3D volume output. */
    void GenerateOutputInformation() override;

    /** \brief Set the requested region on the input to match the selected time step and channel. */
    void GenerateInputRequestedRegion() override;

    /** \brief Extract the selected volume data from the input image. */
    void GenerateData() override;

    int m_TimeNr;

    int m_ChannelNr;
  };


  /**
   * \brief Convenience helper to extract a single time step from a 4D image.
   *
   * If a nullptr is passed as image, a nullptr will be returned.
   * If an image without time steps is passed, the image will be returned unaltered.
   * The behavior for invalid time step values is similar to the ImageTimeSelector filter.
   *
   * \param image The input image (may be nullptr).
   * \param timestep The time step index to extract.
   * \return The extracted 3D image for the given time step (const version).
   *
   * \sa ImageTimeSelector
   */
  MITKCORE_EXPORT Image::ConstPointer SelectImageByTimeStep(const Image* image, unsigned int timestep);

  /**
   * \brief Non-const version of SelectImageByTimeStep.
   *
   * \param image The input image (may be nullptr).
   * \param timestep The time step index to extract.
   * \return The extracted 3D image for the given time step.
   *
   * \sa ImageTimeSelector
   */
  MITKCORE_EXPORT Image::Pointer SelectImageByTimeStep(Image* image, unsigned int timestep);

  /**
   * \brief Convenience helper to extract a single time step from a 4D image by time point.
   *
   * If a nullptr is passed as image, a nullptr will be returned.
   * If an image without time steps is passed, the image will be returned unaltered.
   * The behavior for invalid time point values is similar to the ImageTimeSelector filter.
   *
   * \param image The input image (may be nullptr).
   * \param timePoint The time point to extract.
   * \return The extracted 3D image for the given time point (const version), or nullptr if the time point is invalid.
   *
   * \sa ImageTimeSelector
   */
  MITKCORE_EXPORT Image::ConstPointer SelectImageByTimePoint(const Image* image, TimePointType timePoint);

  /**
   * \brief Non-const version of SelectImageByTimePoint.
   *
   * \param image The input image (may be nullptr).
   * \param timePoint The time point to extract.
   * \return The extracted 3D image for the given time point, or nullptr if the time point is invalid.
   *
   * \sa ImageTimeSelector
   */
  MITKCORE_EXPORT Image::Pointer SelectImageByTimePoint(Image* image, TimePointType timePoint);

} // namespace mitk

#endif
