// ================================================================================ //
//       THE CONTENT OF THIS WORK IS PROPRIETARY TO FEI S.A.S, (FEI S.A.S.),        //
//                  AND IS DISTRIBUTED UNDER A LICENSE AGREEMENT.                   //
//                                                                                  //
//     REPRODUCTION, DISCLOSURE,  OR USE,  IN WHOLE OR IN PART,  OTHER THAN AS      //
//     SPECIFIED  IN THE LICENSE ARE  NOT TO BE  UNDERTAKEN  EXCEPT WITH PRIOR      //
//                       WRITTEN AUTHORIZATION OF FEI S.A.S.                        //
//                                                                                  //
//                             RESTRICTED RIGHTS LEGEND                             //
//     USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT OF THE CONTENT OF THIS     //
//     WORK OR RELATED DOCUMENTATION IS SUBJECT TO RESTRICTIONS AS SET FORTH IN     //
//     SUBPARAGRAPH (C)(1) OF THE COMMERCIAL COMPUTER SOFTWARE RESTRICTED RIGHT     //
//     CLAUSE  AT FAR 52.227-19  OR SUBPARAGRAPH  (C)(1)(II)  OF  THE RIGHTS IN     //
//        TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 52.227-7013.         //
//                                                                                  //
//                         COPYRIGHT (C) 2022 BY FEI S.A.S,                         //
//                                 BORDEAUX, FRANCE                                 //
//                               ALL RIGHTS RESERVED                                //
//                                                                                  //
// SEE http://assets.thermofisher.com/TFS-Assets/MSD/Licensing-Information/FEI_SAS_Thermo-Fisher-EULA_GLOBAL_With Usage Log_Nov2020.pdf //
//                              FOR MORE INFORMATION.                               //
// ================================================================================ //

#pragma once

#include <memory>
#include <string>

#include <iolink/view/ImageView.h>

#include <ioformat/IOFormatAPI.h>

namespace ioformat
{

/**
 * A factory to read stacks of images.
 */
class IOFORMAT_API StackReader
{
public:
  /**
   * Remove constructor, as this class is a static factory.
   */
  StackReader() = delete;

  /**
   * Open multiple files to stack them.
   *
   * The pattern must be written using the character "*" as a wildcard
   * for any number of characters. The wildcard must only be present
   * on the last segment of the path, the filename part.
   *
   * Example:
   *
   * `/some/dir/img_*.png` will load all files following this pattern,
   * ands stack them, using lexicographic order.
   *
   * @param pattern The pattern to use to open files.
   * @param newDim The interpretation of the stacking dimension.
   * @throw Error if stacking failed
   *
   * @return An ImageView containing the images loaded using the pattern, and stacked.
   *
   * @see IOFormat::stack
   *
   */
  static std::shared_ptr<iolink::ImageView> openImageFromPattern(const std::string& pattern,
                                                                 iolink::ImageDimension newDim);

  /**
   * Open multiple files to stack them.
   *
   * The pattern must be written using the character "*" as a wildcard
   * for any number of characters. The wildcard must only be present
   * on the last segment of the path, the filename part.
   *
   * Example:
   *
   * `/some/dir/img_*.png` will load all files following this pattern,
   * ands stack them, using lexicographic order.
   *
   * As there is no dimension specified in this version, the ImageType of the
   * output image will be ImageTYpeId::UNKNOWN
   *
   * @param pattern The pattern to use to open files.
   * @throw Error if stacking failed
   *
   * @return An ImageView containing the images loaded using the pattern, and stacked.
   *
   * @see IOFormat::stack
   *
   */
  static std::shared_ptr<iolink::ImageView> openImageFromPattern(const std::string& pattern);

  /**
   * Stack multiple files following a pattern and load the stacked ImageView in memory.
   *
   * The pattern must be written using the character "*" as a wildcard
   * for any number of characters. The wildcard must only be present
   * on the last segment of the path, the filename part.
   *
   * The stack will be loaded in memory after construction.
   *
   * Example:
   *
   * `/some/dir/img_*.png` will load all files following this pattern,
   * ands stack them, using lexicographic order.
   *
   * @param pattern The pattern to use to open files.
   * @param newDim The interpretation of the stacking dimension.
   * @throw Error if stacking failed
   *
   * @return An ImageView containing the images opened using the pattern, stacked, and
   * loaded in memory.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> readImageFromPattern(const std::string& pattern,
                                                                 iolink::ImageDimension newDim);

  /**
   * Stack multiple files following a pattern and load the stacked ImageView in memory.
   *
   * The pattern must be written using the character "*" as a wildcard
   * for any number of characters. The wildcard must only be present
   * on the last segment of the path, the filename part.
   *
   * The stack will be loaded in memory after construction.
   *
   * Example:
   *
   * `/some/dir/img_*.png` will load all files following this pattern,
   * ands stack them, using lexicographic order.
   *
   * As there is no dimension specified in this version, the ImageType of the
   * output image will be ImageTYpeId::UNKNOWN
   *
   * @param pattern The pattern to use to open files.
   * @throw Error if stacking failed
   *
   * @return An ImageView containing the images opened using the pattern, stacked, and
   * loaded in memory.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> readImageFromPattern(const std::string& pattern);

  /**
   * Stack multiple files as described in a list file.
   *
   * A list file is a file, usually with the "lst" extension, where each
   * line is a path to a file, absolute, or relative to the list file.
   *
   * Example of a list file:
   *
   * @code
   * some/path/to/a/file.ext
   * some/other/path/to/a/file.ext
   * ...
   * @endcode
   *
   * @param filePath The path to the list file.
   * @param newDim The interpretation of the stacking dimension.
   * @throw Error if a file from the list is not found
   * @throw Error if stacking failed
   *
   * @return An ImageView built by stacking all the images in the list file.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> openImageFromListFile(const std::string& filePath,
                                                                  iolink::ImageDimension newDim);

  /**
   * Stack multiple files as described in a list file.
   *
   * A list file is a file, usually with the "lst" extension, where each
   * line is a path to a file, absolute, or relative to the list file.
   *
   * Example of a list file:
   *
   * @code
   * some/path/to/a/file.ext
   * some/other/path/to/a/file.ext
   * ...
   * @endcode
   *
   * @param filePath The path to the list file.
   * @throw Error if a file from the list is not found
   * @throw Error if stacking failed
   *
   * @return An ImageView built by stacking all the images in the list file.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> openImageFromListFile(const std::string& filePath);

  /**
   * Stack multiple files as described in a list file and load the result in memory.
   *
   * A list file is a file, usually with the "lst" extension, where each
   * line is a path to a file, absolute, or relative to the list file.
   *
   * Example of a list file:
   *
   * @code
   * some/path/to/a/file.ext
   * some/other/path/to/a/file.ext
   * ...
   * @endcode
   *
   * @param filePath The path to the list file.
   * @param newDim The interpretation of the stacking dimension.
   * @throw Error if a file from the list is not found
   * @throw Error if stacking failed
   *
   * @return An ImageView built by stacking all the images in the list file and loading it in memory.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> readImageFromListFile(const std::string& filePath,
                                                                  iolink::ImageDimension newDim);

  /**
   * Stack multiple files as described in a list file and load the result in memory.
   *
   * A list file is a file, usually with the "lst" extension, where each
   * line is a path to a file, absolute, or relative to the list file.
   *
   * Example of a list file:
   *
   * @code
   * some/path/to/a/file.ext
   * some/other/path/to/a/file.ext
   * ...
   * @endcode
   *
   * @param filePath The path to the list file.
   * @throw Error if a file from the list is not found
   * @throw Error if stacking failed
   *
   * @return An ImageView built by stacking all the images in the list file and loading it in memory.
   *
   * @see IOFormat::stack
   */
  static std::shared_ptr<iolink::ImageView> readImageFromListFile(const std::string& filePath);
};

} // end namespace ioformat
