#pragma once

#include <conio.h>
#include <time.h>
#include <chrono>
#include <iostream>
#include <sstream>
#include <queue>
#include "Rx.LFR/LightFieldRuntime.h"
#include "Rx.LFR/ICudaData.h"
#include "Rx.LFR/CameraServer.h"
#include "Rx.LFR/CalibrationManager.h"
#include "Rx.LFR/SeqFileWriter.h"
#include "Rx.LFR/SeqFileReader.h"
#include "Rx.LFR/Cuda.h"
#include "Rx.LFR/CudaCompute.h"
#include "Rx.LFR/ImageQueue.h"

#include "Rx.Core\RxException.h"
#include "Rx.CluViz.Core.CluVizTool/CvCluVizTool.h"

#include "ofThread.h"

#include "RxProcessor.h"

#include "DataProcessor.h"

#include "Poco/Timestamp.h"
#include "Poco/Timer.h"
#include "Poco/Stopwatch.h"

#include <lcm/lcm-cpp.hpp>
#include "recorder_status.hpp"

class RxCamera : public ofThread {

public:

	enum IMAGE_DISPLAY_TYPE {
		RAW = 0,
		TOTAL_FOCUS = 1,
		DEPTH_MAP = 2,
		REFOCUS = 3
	};
	
	RxCamera(double exposureTime,double frameRate, double recordRate, double displayRate, double logRate);
	~RxCamera();
	int start();
	int stop();
	void threadedFunction();
	void OnImageCaptured(const Rx::CRxImage& xImage, unsigned uCamIdx);
	void OnSimulatedImage(Poco::Timer&);
	void deployImage(Rx::CRxImage xImage);
	void setDisplayType(RxProcessor::IMAGE_DISPLAY_TYPE t);
	bool haveCamera();
	void startRecording();
	void setRates(double frameRate, double recordRate, double displayRate, double logRate);
	void stopRecording();
	bool isRecording();
	void recStatMsg(const lcm::ReceiveBuffer* rbuf, const std::string& chan, const exlcm::recorder_status* msg);
	void estimateFrameRate();

private:

	int frameCounter;

	bool bSimCamera;
	bool bRealCamera;
	bool bValidCamera;
	bool bWriteImages;

	//queue<unsigned char *> imageQueue;
	queue<Rx::CRxImage> imageQueue;

	Poco::Timer simCameraCapture;

	Rx::LFR::CImageQueue m_xCamBuffer;
	Rx::LFR::CRayImage readImage;
	Rx::LFR::CSeqFileWriter seqWriter;
	Rx::LFR::CSeqFileReader seqReader;
	Rx::LFR::CCameraServer xCamServer;
	Rx::LFR::CCudaCompute xCudaCompute;
	Rx::LFR::CCalibration xDefaultCalibration;
	Rx::CRxString sxCameraName;
	Rx::CRxString sxName;
	Rx::LFR::ICudaDataImages* pxImages;
	Rx::CRxImage xCapturedImage;
	Rx::CRxImage xOutputImage;
	Rx::LFR::CMetaData metaData;

	Rx::CRxImageFormat imageFormat;

	RxProcessor imgProc;
	std::chrono::high_resolution_clock::time_point recordClockStart;
	std::chrono::high_resolution_clock::time_point logClockStart;
	std::chrono::high_resolution_clock::time_point frameClockStart;
	std::chrono::high_resolution_clock::time_point displayClockStart;

	double lastFrameTimestamp;


	int lastFrameCount;

	float frameRate;
	float saveToDiskRate;
	float displayRate;
	float logRate;
	float exposureTime;
	float gain;

	double dFocus;

	unsigned char* tmpImage;
	
	double dClockMHz;
	double frameRateEst;
	double dGlobalMemMB;
	unsigned int uID;
	int iHandle;
	unsigned uBufferSize;
	bool bOverwrite;
	bool imageUpdated;

	IMAGE_DISPLAY_TYPE displayType;


};
