/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#include "DLLInterface.h"
#include "Pimpl.h"

#include "Calibration.h"
#include "RayImage.h"

#include "Rx.Core.Ex/RxImage.h"
#include "Rx.Core.Ex/RxMetaData.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx.LFR
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	namespace LFR
	{
		class CSeqFileReader_Impl;

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Provides methods for reading a ray sequence from a rays file.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class RX_API CSeqFileReader : public CPimpl<CSeqFileReader_Impl, Interfaces::ESeqFileReader::ID>
		{
		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Default constructor.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileReader();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move constructor.
			/// </summary>
			///
			/// <param name="xSeqFileReader"> [in,out] The sequence file reader instance. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileReader(CSeqFileReader&& xSeqFileReader);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Destructor. Closes the file if opened.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			~CSeqFileReader();

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Opens the given ray sequence for reading.
			///
			/// 	To read the first frame, you have to call StartReading. Then you can call ReadFrame to read frame by frame.
			///
			/// 	Requires an authenticated dongle (Rx::LFR::CLightFieldRuntime::Authenticate).
			/// </summary>
			///
			/// <param name="sxFilename">		 The file name. </param>
			/// <param name="uFrameBufferCount"> (Optional) Number of frames to buffer. Must NOT be zero. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void Open(const CRxString& sxFilename, unsigned uFrameBufferCount = 2);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Reads the first frame including the meta data and the calibration. This starts the background buffer thread.
			/// </summary>
			///
			/// <param name="xRayImg"> [out] The ray image. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void StartReading(CRayImage& xRayImg);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Reads the frame at the current frame index. Reads the frame from buffer if already buffered.
			///
			/// 	To read the first frame, you have to call StartReading after calling Open.
			/// </summary>
			///
			/// <param name="xFrame"> [out] The frame. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ReadFrame(CRxImage& xFrame);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Closes the opened sequence file and stops the background buffer thread.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void Close();

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Moves the current frame index by the given number forward or backward.
			/// </summary>
			///
			/// <param name="iDelta"> The number of frames to move the current index. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void MoveFrameIndex(int iDelta);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the current frame index.
			/// </summary>
			///
			/// <param name="uNewIdx"> The new frame index. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetFrameIndex(unsigned uNewIdx);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if a file has been opened.
			/// </summary>
			///
			/// <returns> True if open, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsOpen() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the current number of used buffer slots.
			/// </summary>
			///
			/// <returns> The used frame buffer count. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetUsedFrameBufferCount();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the number of frames in the opened sequence.
			/// </summary>
			///
			/// <returns> The frame count. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetFrameCount() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the size of a frame in bytes.
			/// </summary>
			///
			/// <returns> The frame size. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetFrameSize() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the current frame index.
			/// </summary>
			///
			/// <returns> The frame index. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetFrameIndex() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the file size in bytes.
			/// </summary>
			///
			/// <returns> The file size. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			uint64_t GetFileSize() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the double shot mode of the opened sequence. Is 0 if the sequence wasn't recorded in double shot mode.
			/// </summary>
			///
			/// <returns> The double shot mode. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetDoubleShotMode() const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move assignment operator.
			/// </summary>
			///
			/// <param name="xSeqFileReader"> [in,out]The sequence file reader instance. </param>
			///
			/// <returns> The instance. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileReader& operator=(CSeqFileReader&& xSeqFileReader);
		};
	}
}
