/**
 * \file    Mimic_Camera.hpp
 * \author  Silvan Murer
 * \date    24 September 2022
 *
 * \brief   Mimic_Camera - Class get access to the device component defined by GenTL
 */

#ifndef INC_MIMIC_CAMERA
#define INC_MIMIC_CAMERA

#include "Mimic_NodeMap.hpp"
#include "Mimic_Buffer.hpp"
#include "Mimic_Exception.hpp"

#include <stdint.h>
#include <string>
#include <vector>

namespace spdlog {
	class logger; ///< forward declaration of internal used logger object
}
namespace genSDK {
	class GTL_Producer; ///< forward declaration of GTL_Producer
}
namespace GenTL {
	typedef void* DEV_HANDLE; ///< declaration of GenTL system handle
	typedef void* DS_HANDLE;  ///< declaration of GenTL data stream handle
	typedef void* EVENT_HANDLE;  ///< declaration of GenTL event handle
	typedef void* BUFFER_HANDLE;  ///< declaration of GenTL buffer handle
}
namespace GenApi_3_4 {
	class CEventAdapterGeneric; ///< forware declaration of GenAPI event handler
}

namespace mimic {

 /**
 * Camera class of the Mimic Library
 *
 * This class get access to the device component of a GenTL producer.
 * It configure the GenTL camera and acquire data from it.
 * Data access is realized through a Buffer object.
 */
class Mimic_Camera {
private:
	std::shared_ptr<spdlog::logger> logger; ///< shared pointer to a simple console logger
	std::shared_ptr<genSDK::GTL_Producer> gtl_producer; ///< shared pointer to the gtl_producer
	GenTL::DEV_HANDLE devH; ///< C handle to the GenTL device component
	GenTL::DS_HANDLE dsH;   ///< C handle to the GenTL data stream component
	GenTL::EVENT_HANDLE newBufEvtH;   ///< C handle to the GenTL new buffer event
	std::vector<GenTL::BUFFER_HANDLE> bufHVec;  ///< vector containing C handles of the GenTL buffer component

	std::shared_ptr<GenApi_3_4::CEventAdapterGeneric> eventAdapter;

	bool inAcquisition;

public:
	Mimic_NodeMap nodeMap; ///< device node map

	/**
	 * \brief no default constructor is available for this class
	 */
	Mimic_Camera() = delete;

	/**
	 * \brief constructor to create a Camera instance
	 *
	 * Don't create a Camera by your self. Use the Mimic_Producer::openCamera method!
	 */
	Mimic_Camera(std::shared_ptr<genSDK::GTL_Producer> gtl_producer, GenTL::DEV_HANDLE devH);

	/**
	 * \brief copy constructor
	 */
	Mimic_Camera(const Mimic_Camera& other) = delete;
	/**
	 * \brief copy assignment not supported by this class
	 */
	Mimic_Camera& operator=(const Mimic_Camera& other) = delete;

	/**
	 * \brief move constructor
	 */
	Mimic_Camera(Mimic_Camera&& other) noexcept;
	/**
	 * \brief move assignment not supported by this class
	 */
	Mimic_Camera& operator=(Mimic_Camera&& other) = delete;

	/**
	 * \brief destructor
	 */
	~Mimic_Camera();

	/**
	 * \brief function to release a device.
	 *
	 * A call to this function release all allocated memory and Buffers generated by this device.
	 */
	void release();
	/**
	 * \brief read the device name
	 *
	 * \return a string value including the device name
	 */
	std::string getDeviceName();


	/* device state configuration */
	/**
	 * \brief switch to acquisition state
	 */
	void startAcquisition(int64_t nofBuf = 4);
	/**
	 * \brief switch to acquisition stop / configuration state
	 */
	void stopAcquisition();

	/**
	 * \brief check if a data buffer available and return it
	 *
	 * \param[in]   timeout_ms time to wait when no data are available
	 * 
	 * \exception Mimic_Timeout_Exception exception when no data available, 
	 *            Mimic_GenTL_Exception exception when producer access failed.
	 * \return Mimic_Buffer object containing the data
	 */
	Mimic_Buffer getBuffer(uint32_t timeout_ms = 1000);

};

} /* namespace mimic */

#endif
