#pragma once

#include <fsdk/FSDKError.h>
#include <fsdk/Types.h>

#include <fsdk/vlc/future.h>

#include <fsdk/IImagesBatch.h>

namespace fsdk {

#ifndef DOXYGEN_SHOULD_SKIP_THIS
	DECLARE_SMARTPTR(IImageTransfer);
#endif

	/**
	 * @defgroup ImageTransferGroup ImageTransfer
	 * @brief ImageTransfer public interfaces and related types and structures.
	 * @{
	 * */

	/**
	 * @brief Image transfer facility which give speed up of usage internal memory pool.
	 * @note This module designed to work only while FaceEngine initialized.
	 * Usage of this module after FaceEngine destruction is undefined behaviour.
	 * @note This module is only make sense to use if user get sdk compiled with cuda support
	 * and if user set deviceClass to GPU nevertheless transfer accomplished CPU -> GPU or reverse.
	 * */
	struct IImageTransfer : IRefCounted {

		/**
		 * @brief Transfer of multiple images.
		 * @param [in] images span of source images.
		 * @param [in] residence desired destination residence.
		 * @return ResultValue with error code and IImagesBatch object.
		 * @see Ref, Span, Image, MemoryResidence, IImagesBatch, ResultValue and FSDKError for details.
		 * @note all spans should be based on user owned continuous collections.
		 * */
		virtual ResultValue<FSDKError, Ref<IImagesBatch>>
		transfer(Span<const Image> images, Image::MemoryResidence residence) const noexcept = 0;

		/**
		 * @brief Validate input of multiple frames in a single function call.
		 * @param [in] images span of source images.
		 * @param [in] residence desired destination residence.
		 * @param [out] errors output span of errors for each image.
		 * @return Result with error code.
		 * @see Span, Image, MemoryResidence, Result and FSDKError for details.
		 * @note all spans should be based on user owned continuous collections.
		 * @note all spans should be equal size.
		 * */
		virtual Result<FSDKError> validate(
			Span<const Image> images,
			Image::MemoryResidence residence,
			Span<Result<FSDKError>> errors) const noexcept = 0;

		/**
		 * @brief Common alias for IImageTransfer asynchronous interface.
		 * */
		using ImagesBatchFuture = vlc::future<IImagesBatchPtr>;

		/**
		 * @brief Asynchronously transfer multiple images.
		 * @param [in] images span of source images.
		 * @param [in] residence desired destination residence.
		 * @return Future with IImagesBatch object.
		 * @see Ref, Span, Image, MemoryResidence, IImagesBatch
		 * vlc::future for details.
		 * @note all spans should be based on user owned continuous collections.
		 * @note this method is experimental and interface may be changed in the future.
		 * @note this method is not marked as noexcept and may throw an exception.
		 * */
		virtual ImagesBatchFuture
		transferAsync(Span<const Image> images, Image::MemoryResidence residence) const = 0;
	};

	/** @} */
} // namespace fsdk
