#ifndef VIDEODISPLAY_H_
#define VIDEODISPLAY_H_

#include "framework.h"
#include "MyEnum.h"
#include "ImageBuilder.h"
#include <fstream>
#include <string>
#include <vector>
#include <atlimage.h>
#include "Resource.h"

namespace thermoCamera {

	/**
	* @class VideoDiplay
	* @brief Display an input image on the screen
	* libirimager is used from url:
	* http://documentation.evocortex.com/libirimager2/html/index.html
	* @author Matej Roman (student of BUT)
	*/
	class VideoDisplay {

	public:

		VideoDisplay() :
			_isSetManualTemperatureRange(false),
			_isSetRelativeTemp(false),
			_image(NULL),
			_imageBar(NULL),
			_thermalDataFromRecord(NULL),
			_RawData(NULL),
			_alarmThreshold(37.f),
			_sizeOfInputImageDevice{0,0},
			_minMaxRangeTemp{0.f,0.f},
			_pointTempMouse{0,0},
			_temperatureMouse(0.f),
			_calibratedValue(0.f),
			_method(evo::eMinMax),
			_palette(evo::eIron),
			_hWnd(NULL),
			_backbuffer(NULL),
			_hBitMap(NULL)
		{}

		~VideoDisplay()
		{
			_absolutePositionForDisplay.clear();
			if(_RawData) { delete[] _RawData; _RawData = NULL; }
			if (_image) { delete[] _image; _image = NULL; }
			if (_imageBar) {  _imageBar = NULL; }
			if (_thermalDataFromRecord) { delete[] _thermalDataFromRecord; _thermalDataFromRecord = NULL; }
		}

		void Draw(const HDC& hdc, const RECT& rect, const HDC buffer) const;

		void DrawTemperature(const HDC& hdc,const COLORREF color, float regionTemp);

		void DrawMinMaxTempBar(const HDC& hdc,RECT& positonBar);

		void ValidateRect(const RECT& rect) const;

		// 0 max, 1 average
		float ReturnTemperature(RECT rc, int method);

		bool Show(int left,int top,int width, int height, int widthOut, int heightOut, unsigned short** data);

		bool ShowWhilePause(int left, int top, int width, int height, int widthOut, int heightOut);

		void EraseAndUpdateWindow();

		void ChangePallete(int& index);

		void SaveData(const TCHAR* path, unsigned int num);

		void SaveBitMap(HBITMAP hBitMap,const TCHAR* path, unsigned int num);

		void SaveScreenShot(HWND hWnd,RECT screen, const TCHAR* path, unsigned int num);

		void LoadData(const TCHAR* path, unsigned int num);

		void LoadWidthHeight(const TCHAR* path, SIZE& sizeOfImage, size_t numberOfTxt);

		void DeleteObjects();

		void DeleteObjects(int index);

		void SetHWND(HWND hWnd) { _hWnd = hWnd; }

		void SetHDC(HDC hdc) { _backbuffer.push_back(hdc); }

		void SetHDC(HDC hdc, int index) { _backbuffer.insert(_backbuffer.begin() + index, hdc); }

		void SetBitMap(HBITMAP hBitMap) { _hBitMap.push_back(hBitMap); }

		void SetBitMap(HBITMAP hBitMap,int index) { _hBitMap.insert(_hBitMap.begin()+index,hBitMap); }

		void SetCalibratedValue(float& value) { _calibratedValue = value; }

		void SetAbsolutePosition(RECT& rect) { _absolutePositionForDisplay.push_back(rect); }

		void SetPosition(RECT &rect, int index);

		void SetAlarmThreshold(float alarm) { _alarmThreshold = alarm; }

		void SetManualRangeTemperature() { _isSetManualTemperatureRange = true; }

		void ResetManualRangeTemperature() { _isSetManualTemperatureRange = false; }

		void SetRelativeTemp() { _isSetRelativeTemp = true; }

		void ResetRelativeTemp() { _isSetRelativeTemp = false; }

		bool isSetManualRangeTemperature() { return _isSetManualTemperatureRange; }

		void SetMinRangeTemperature(float min) { _minMaxRangeTemp.first = min; }

		void SetMaxRangeTemperature(float max) { _minMaxRangeTemp.second = max; }

		void EraseHDC(int index);

		void EraseBitMap(int index);

		float GetTemperature(int x, int y, bool isStretchCoordinatesNeeded);

		float GetCalibratedValue() { return _calibratedValue; }

		float GetAlarmThreshold() {return _alarmThreshold; }

		HWND GetMainWindow() { return _hWnd; }

		HDC GetHDC(int index);

		HBITMAP GetHBITMAP(int index);

		SIZE GetSizeOfInputImage() { return _sizeOfInputImageDevice; }

		RECT GetSizeOfVideo(int index);

		bool IsSetRelativeTemp() { return _isSetRelativeTemp; }

		float GetMinRangeTemperature() { return _minMaxRangeTemp.first; }

		float GetMaxRangeTemperature() { return _minMaxRangeTemp.second; }

		unsigned short** GetThermalFromRecord() { return &_thermalDataFromRecord; }

	private:

		bool _isSetManualTemperatureRange;

		bool _isSetRelativeTemp;

		unsigned char* _image;

		unsigned char* _imageBar;

		unsigned short *_thermalDataFromRecord;

		unsigned short* _RawData;

		float _alarmThreshold;

		std::vector<RECT> _absolutePositionForDisplay;

		std::pair<float, float> _minMaxRangeTemp;

		SIZE _sizeOfInputImageDevice;

		POINT _pointTempMouse;

		float _temperatureMouse;

		float _calibratedValue;

		evo::EnumOptrisPaletteScalingMethod _method;

		evo::ImageBuilder _imageBuilder;

		evo::EnumOptrisColoringPalette _palette;

		HWND _hWnd;

		std::vector<HDC> _backbuffer;

		std::vector<HBITMAP> _hBitMap;

		void _ShowThermalImage(int x, int y, int width, int height, int widthOut, int heightOut);

		void _ShowThermalImageForDetection(int x, int y, int width, int height, int widthOut, int heightOut);

		void _ShowThermalImageBar(int x, int y, int width, int height, int widthOut, int heightOut);

		bool _ProcessOutput(int& width,int& height, int& widthOut, int& heightOut);

		void _StretchWindow(RECT& input, RECT& output, int newWidth, int newHeight);

		bool _CheckInput(int& left, int& top, int& width, int& height, int& widthOut, int& heightOut, unsigned short**& data);

		bool _CheckInput(int& left, int& top, int& width, int& height, int& widthOut, int& heightOut);

		void _fromStretched2RealCoordinates(int& x, int& y, int& xReal, int& yReal);

		void _transformLinear2D(int& x, int& y, int& xReal, int& yReal, float inlox, float inupx, float outlox, float outupx, float inloy, float inupy, float outloy, float outupy);

		float _getMaxTemperature(RECT& rc);
	};

}

#endif
