#pragma once

#include <conio.h>
#include <chrono>
#include <iostream>
#include <sstream>
#include <fstream>
#include <queue>
#include "Rx.LFR/LightFieldRuntime.h"
#include "Rx.LFR/ICudaData.h"
#include "Rx.LFR/CalibrationManager.h"
#include "Rx.LFR/Cuda.h"
#include "Rx.LFR/CudaCompute.h"
#include "Rx.LFR/ImageQueue.h"
#include "math.h"

#include "opencv2/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/videoio.hpp"

#include "Rx.Core\RxException.h"
#include "Rx.CluViz.Core.CluVizTool/CvCluVizTool.h"
//#include "Rx.CluViz.Core.ST/ST.h"

#include "ofThread.h"

#include "Poco/Timestamp.h"
#include "Poco/Timer.h"
#include "Poco/Stopwatch.h"

#include <lcm/lcm-cpp.hpp>
#include "total_focus_image.hpp"
#include "recorder_status.hpp"

class RxProcessor : public ofThread {

public:

	enum IMAGE_DISPLAY_TYPE {
		RAW = 0,
		TOTAL_FOCUS = 1,
		DEPTH_MAP = 2,
		REFOCUS = 3,
		PARTICLE = 4
	};

	RxProcessor();
	RxProcessor(unsigned int uID, Rx::LFR::CCalibration& xDefaultCalibration);
	~RxProcessor();
	void setCameraCalibration(unsigned int uID, Rx::LFR::CCalibration& xDefaultCalibration);
	void setImageFormat(Rx::CRxImageFormat fmt);
	int start();
	int stop();
	void threadedFunction();
	void addImage(Rx::CRxImage xImage);
	void drawImage(Rx::CRxImage& img);
	void totalFocusProc();
	void depthMapProc();
	void refocusProc();
	void particleStats();
	void flipImage(Rx::CRxImage& img, int dir);
	void setVideoOutputFile(string name);
	int queueSize();
	void rawImageProc();
	void initCudaWithImage();
	void setDisplayType(IMAGE_DISPLAY_TYPE t);

private:

	queue<unsigned char*> imageQueue;
	//queue<Rx::CRxImage> imageQueue;

	cv::VideoWriter outputVideo;

	Rx::LFR::CCudaCompute xCudaCompute;
	Rx::LFR::ICudaDataImages* pxImages;
	Rx::LFR::CImageQueue m_xImageBuffer;
	Rx::CRxImage xCapturedImage;
	Rx::CRxImage xOutputImage;
	Rx::CRxImage xTFImage;
	Rx::CRxImage xDepthImage;
	Rx::CRxImageFormat imageFormat;
	
	unsigned int uID;
	int iHandle;
	int frameCounter;
	int displayRate;
	double dFocus;
	std::chrono::high_resolution_clock::time_point displayClockStart;

	string outputFile;

	lcm::LCM lcm;
	exlcm::recorder_status recStat;
	exlcm::total_focus_image lcmImage;

	bool haveCameraCal;
	bool imageUpdated;
	bool cudaReady;
	bool downsample;
	bool imageOverLCM;

	cv::Mat tmpImage;

	IMAGE_DISPLAY_TYPE displayType;



};
