/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#include "DLLInterface.h"
#include "ParametersPimpl.h"
#include "Parameters.h"

#include "CudaDevice.h"
#include "Rx.LFR/RayImage.h"
#include "Rx.LFR/Types_HighResolutionParticleDetection.h"
#include "Rx.LFR/Calibration.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx.LFR
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	namespace LFR
	{
		class CHighResolutionParticleDetector_Impl;
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Provides methods to perform high resolution particle detection.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		class RX_API CHighResolutionParticleDetector : public CParametersPimpl<CHighResolutionParticleDetector_Impl, Params::EHighResolutionParticleDetector::ID, Interfaces::EHighResolutionParticleDetector::ID>
		{
		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Default constructor.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CHighResolutionParticleDetector();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move constructor.
			/// </summary>
			///
			/// <param name="xHighResolutionParticleDetector"> [in,out] The high resolution particle detection instance. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CHighResolutionParticleDetector(CHighResolutionParticleDetector&& xHighResolutionParticleDetector);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Destructor.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			~CHighResolutionParticleDetector();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Initializes this object.
			/// </summary>
			///
			/// <param name="xCalib"> The calibration. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void Initialize(const CCalibration& xCalib);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Adds an image to background.
			/// </summary>
			///
			/// <param name="xImage"> The image. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void AddImageToBackground(const  Rx::LFR::CRayImage& xImage);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Calculates the background.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ComputeBackground();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Detect particles.
			/// </summary>
			///
			/// <param name="sSequenceFilename"> Filename of the sequence file. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void DetectParticles(const Rx::CRxString& sSequenceFilename);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Detect particles.
			/// </summary>
			///
			/// <param name="xImage"> [in] The image. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void DetectParticles(const  Rx::LFR::CRayImage& xImage);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Filter tracks.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void CreateHighResolutionTracks();

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets an image.
			///
			/// 	0 = Foreground image.
			/// 	1 = Blurred foreground image.
			/// </summary>
			///
			/// <param name="xImage"> [out] The image. </param>
			/// <param name="iImage"> Image Type </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetImage(CRxImage& xImage, int iImage);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets found ellipses.
			/// </summary>
			///
			/// <param name="axEllipses"> [out] The ellipses array. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetFoundEllipses2D(Rx::CRxArray<ParticleDetection::SEllipses2D>& axEllipses);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets found ellipses.
			/// </summary>
			///
			/// <param name="axEllipses"> [out] The ellipses array. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetFoundEllipses3D(Rx::CRxArray<ParticleDetection::SEllipses3D>& axEllipses);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets found high resolution particle.
			/// </summary>
			///
			/// <param name="axHighResolutionParticles"> [out] The high resolution particle array. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetFoundHighResolutionParticles(Rx::CRxArray<ParticleDetection::SHighResolutionParticle>& axHighResolutionParticles);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets found tracks.
			/// </summary>
			///
			/// <param name="axTracks"> [in,out] The tracks. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetFoundTracks(Rx::CRxArray<ParticleDetection::STrack>& axTracks);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets high resolution particle tracks.
			/// </summary>
			///
			/// <param name="axTracks"> [in,out] The tracks. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetHighResolutionParticleTracks(Rx::CRxArray<ParticleDetection::STrack>& axTracks);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the CUDA device for the high resolution particle detector.
			/// </summary>
			///
			/// <param name="xCudaDevice"> The CUDA device. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetCudaDevice(const CCudaDevice& xCudaDevice);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Move assignment operator.
			/// </summary>
			///
			/// <param name="xHighResolutionParticleDetector"> [in,out] The high resolution particle detection instance. </param>
			///
			/// <returns> The instance. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CHighResolutionParticleDetector& operator=(CHighResolutionParticleDetector&& xHighResolutionParticleDetector);
		};
	}
}
