/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2015 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#include "DLLInterface.h"
#include "Pimpl.h"

#include "Calibration.h"

#include "Rx.Core.Ex/RxImage.h"
#include "Rx.Core.Ex/RxMetaData.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx.LFR
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	namespace LFR
	{
		class CSeqFileWriter_Impl;

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Provides methods for writing frames into a sequence in a rays file.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class RX_API CSeqFileWriter : public CPimpl<CSeqFileWriter_Impl, Interfaces::ESeqFileWriter::ID>
		{
		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Default constructor.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileWriter();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move constructor.
			/// </summary>
			///
			/// <param name="xSeqFileWriter"> [in,out]The sequence file writer instance. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileWriter(CSeqFileWriter&& xSeqFileWriter);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Destructor. Closes the opened file.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			~CSeqFileWriter();

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Opens the given ray sequence for writing.
			///
			/// 	Requires an authenticated dongle (Rx::LFR::CLightFieldRuntime::Authenticate) with the Rx::Dongle::ERuntimeFeature::Save
			/// 	feature.
			/// </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>
			/// 	Starts the write process. This starts the background buffer thread.
			/// </summary>
			///
			/// <param name="xFrameFormat">    The frame format. </param>
			/// <param name="xCalib">		   The calibration. </param>
			/// <param name="xMeta">		   [in,out] The meta data. </param>
			/// <param name="uDoubleShotMode"> The double shot mode. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void StartWriting(const CRxImageFormat& xFrameFormat, const CCalibration& xCalib, CRxMetaData& xMeta, unsigned uDoubleShotMode);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Writes the given frame at the current frame index.
			/// </summary>
			///
			/// <param name="xFrame"> The frame. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void WriteFrame(const CRxImage& xFrame);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Closes the opened sequence file and stops the background buffer thread.
			/// </summary>
			///
			/// <returns> The number of frames written. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned Close();

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the frame format that has been passed in StartWriting.
			/// </summary>
			///
			/// <returns> The frame format. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			const CRxImageFormat& GetFrameFormat() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the current number of used buffer slots.
			/// </summary>
			///
			/// <returns> The used frame buffer count. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetUsedFrameBufferCount();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the current 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 file size in bytes.
			/// </summary>
			///
			/// <returns> The file size. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			uint64_t GetFileSize() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the double shot mode that has been passed in StartWriting.
			/// </summary>
			///
			/// <returns> The double shot mode. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			unsigned GetDoubleShotMode() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if a file has been opened.
			/// </summary>
			///
			/// <returns> True if open, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsOpen() const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if StartWriting has been called.
			/// </summary>
			///
			/// <returns> True if writing, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsWriting() const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move assignment operator.
			/// </summary>
			///
			/// <param name="xSeqFileWriter"> [in,out]The sequence file writer instance. </param>
			///
			/// <returns> The instance. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CSeqFileWriter& operator=(CSeqFileWriter&& xSeqFileWriter);
		};
	}
}
