#pragma once

#define VRG_API extern "C" __declspec(dllimport)

#define TRACKER_LIGHTHOUSE 0

#define API_DX11   0
#define API_OPENGL 2

// lib version
VRG_API int getVersion();

//initialize HMD
VRG_API void initHMDDevice(int id, unsigned int &error);

// Gets device count
VRG_API unsigned short getHMDDeviceCount();

// Turn on or off IMU
VRG_API void setHMDIMU(int id, bool enabled);

// initialize position tracking (returns 0, if successfully inited)
VRG_API int initHMDPositionTracker(int id, int tracker);

// Reset IMU
VRG_API void resetHMDIMU(int id);

// calibrate HMD (0,0,0) position
VRG_API void setHMDPositionCalibration(int id);

// get GL projection matrices (RH, columns)
VRG_API void getGLProjectionMatrices(int id, float*& L, float*& R, float n = 0.03f, float f = 1000.0f);

// get DirecX projection matrices (rows for initialization with XMMATRIX(L), XMMATRIX(R))
VRG_API void getDXProjectionMatricesLH(int id, float*& L, float*& R, float n = 0.03f, float f = 1000.0f);

// Gets Device framerate and resolution info
VRG_API void getHMDResolutionFramerate(int id, int& w, int& h, int& rate);

//prepare headset for rendering, set graphical API
VRG_API void attachHMDGfxDevice(int id, unsigned int api, void* device);

// get HMD position and orientation
VRG_API void getHMDPositionOrientation(int id, float& x, float& y, float& z, float& qx, float& qy, float& qz, float& qw);

// IPD in meters
VRG_API void getHMDIPDinM(int id, float& lmm, float& rmm);

// left and right are pointers to texture structure or id in OpenGL mode
VRG_API void drawHMDImageLR(int id, void* left, void* right);

// draw sidebyside image (DX mode only right now)
VRG_API void drawHMDImage(int id, void* image);

// Gets last error text
VRG_API char* getHMDLastError();

// free hmd
VRG_API void freeHMDDevice(int id);

/////////////////////////////////////////////////////
//               CALLBACKS                         //
/////////////////////////////////////////////////////
typedef void(*callbackSPP)(int id, float, float);

// Set callback to get IPD values
VRG_API void setCallbackIPDinM(void* function);

// Set callback to get automatic IMU messages
VRG_API void setCallbackIMU(void* function);

// Set callback to get error messages
VRG_API void setCallbackError(void* function);




/////////////////////////////////////////////////////
//               LEGACY FUNCTIONS                  //
/////////////////////////////////////////////////////

//initialize HMDs
VRG_API int initHMDDevices();			

// Free all Devices
VRG_API void freeHMDDevices();	

// Gets display names (return "none" in case of error)
VRG_API void getHMDMonitors(int id, char* left, char* right);

// get GL projection matrix for desired eye
VRG_API float* getGLProjectionMatrix(bool right_eye);

// get projection matrix with near and far planes setting
VRG_API float* getGLProjectionMatrixNearFar(bool right_eye, float n, float f);

// Warping texture access class
struct IWarping {
public:
	virtual void GetProjectionMatrices(float*& L, float*& R) = 0;

	virtual void GetProjectionMatrices(float*& L, float*& R, float near_plane, float far_plane) = 0;

	virtual unsigned int GetBothEyesTexture(unsigned int leftImage, unsigned int rightImage) = 0;

	virtual void GetSeparatedEyesTexture(unsigned int leftImage, unsigned int rightImage, unsigned int& outLeftImage, unsigned int& outRightImage) = 0;

	virtual void Destroy() = 0;
};
// returns IWarping objects to access warped image
VRG_API int getGLWarping(IWarping*& warping);

// Turn on or off IMU magnetometer
VRG_API void setHMDIMUmag(int id, bool enabled);

// IPD in screen space percentage
VRG_API void getHMDIPDScreenPos(int id, float& pL, float& pR);

// prepared function for position tracking
VRG_API void getHMDPosition(int id, float& x, float& y, float& z);

// Gets IMU Quaternion - even if another tracker is initialized
VRG_API void getHMDQuaternion(int id, float &x, float &y, float &z, float &w);

// get warp function
VRG_API char* getwrp();

VRG_API void getHMDScreenRealOrthoCenter(int id, float& left, float& right);

VRG_API void setCallbackIPDScreenPos(void* fnc);






/////////////////////////////////////////////////////
//               NEW VERSION OF API  (beta)        //
/////////////////////////////////////////////////////

typedef void(*CallbackDisconnected)();
typedef void(*CallbackError)(char* error);
typedef void(*IPDCallback)(float& left, float& right);

enum RendererType :int
{
	DX11 = 0,
	DX12 = 1,
	OpenGL = 2,
	Vulkan = 3
};

struct IHMD
{
public:
	// inits renderer for current HMD
	virtual int InitRenderer(RendererType renderer_type, void* device_context, bool single_texture) = 0;
	// gets projection matrices
	virtual void GetProjectionMatrices(float*& left, float*& right) = 0;
	// gets projection matrices for custom near and far planes
	virtual void GetProjectionMatrices(float*& left, float*& right, float near, float far) = 0;
	// draws texture to HMD eyes - NOT ACTIVE YET
	virtual void DrawImage(void* texture) = 0;
	// draws texture to HMD eyes
	virtual void DrawImage(void* left, void* right) = 0;
	// shuts down renderer
	virtual void ShutDown() = 0;
	// gets eye position in meters
	virtual void GetIPDinM(float& left, float& right) = 0;
	// gets internal sensor quaternion
	virtual void GetQuaternion(float& x, float& y, float &z, float& w) = 0;
	// inits tracker 0 = LightHouse, parameter = tracker_id (n-th tracker/puck)
	virtual void InitTracker(int tracker_type, int parameter) = 0;
	// calibrate center (0, 0, 0)
	virtual void TrackerCalibration() = 0;
	// gets positional data and orientation from selected tracker
	virtual void GetPositionOrientation(float& x, float& y, float& z, float& qx, float& qy, float& qz, float &qw) = 0;
	// init direct mode - NOT ACTIVE YET
	virtual void DirectMode(bool enabled) = 0;
	// callbacks
	IPDCallback OnIPD;
	CallbackDisconnected OnDisconnected;
	CallbackError OnError;
};

extern "C" VRG_API int getHMD(int id, IHMD* hmd);
