// dllmain.cpp : Defines the entry point for the DLL application.
#include <iostream>
#include <windows.h>

#include "VRPNDLLClientStructs.h"

#define TEST_DATA_COUNT 100

#define DEVICE_NAME "iOS0@localhost"
#define PRINT_WIRING_DATA

using namespace std;

typedef void (__cdecl * SetupDevice)(const char * deviceName, int buttonsChannel, int yawChannel, int pitchChannel, int rollChannel, int deltaXChannel, int deltaYChannel, int deltaZChannel);
typedef void (__cdecl * StartFunc) ( void ); 
typedef void (__cdecl * StopFunc) ( void );
typedef void (__cdecl * ReadDeviceFunc)(DeviceValues * dValues);

bool sStopVrpnThread;

DWORD WINAPI ThreadDevice (LPVOID pArg);

void PressToContinue()
{
	cout << "Enter a letter to end!\n";
	
	cin.clear(); 
	cin.ignore(INT_MAX,'\n');

	int a;
	cin >> a;
}

int main()
{
	//Load the DLL
	cout << "Loading dll!" << endl;
	HINSTANCE DllInstance = LoadLibrary(TEXT("VRPNDLLClient.dll"));
	if( DllInstance == NULL )
	{
		cout << "Error: Unable to load DLL" << endl;
		PressToContinue();
		return -1;
	}
	else
	{
		cout << "OK: Able to load DLL" << endl;
	}
	
	//Find the setup function
	SetupDevice pSetupDevice = (SetupDevice)GetProcAddress(DllInstance, "VRPNDLLClient_SetupDevice");
	if( pSetupDevice == NULL )
	{
		cout << "Error: Unable to find SetupDevice function" << endl;
		PressToContinue();
		return -1;
	}
	else
	{
		cout << "OK: Able to find SetupDevice function" << endl;
	}
	
	//Find the start function
	StartFunc pStartFunc = (StartFunc)GetProcAddress(DllInstance, "VRPNDLLClient_StartDevice");
	if( pStartFunc == NULL )
	{
		cout << "Error: Unable to find Start function" << endl;
		PressToContinue();
		return -1;
	}
	else
	{
		cout << "OK: Able to find Start function" << endl;
	}
	
	//Find the stop function
	StopFunc pStopFunc = (StopFunc)GetProcAddress(DllInstance, "VRPNDLLClient_StopDevice");
	if( pStopFunc == NULL )
	{
		cout << "Error: Unable to find Stop function" << endl;
		PressToContinue();
		return -1;
	}
	else
	{
		cout << "OK: Able to find Stop function" << endl;
	}
		
	//Find the ReadDeviceFunc
	ReadDeviceFunc pReadDevice = (ReadDeviceFunc)GetProcAddress(DllInstance, "VRPNDLLClient_ReadDevice");
	if( pReadDevice == NULL )
	{
		cout << "Error: Unable to find ReadADevice function" << endl;
		PressToContinue();
		return -1;
	}
	else
	{
		cout << "OK: Able to find ReadDevice function" << endl;
	}

	//Setup 7 Channels
	pSetupDevice(DEVICE_NAME, 0, 1, 2, 3, 4, 5, 6);
	
	sStopVrpnThread = false;
	pStartFunc();
	printf("OK: Will start the thread... \n");
	HANDLE deviceThreadHandle = CreateThread(NULL, 0, &ThreadDevice, (LPVOID)pReadDevice, 0, NULL);

	printf("NEW RUN! \n");
	PressToContinue();
	
	pStopFunc();
	sStopVrpnThread = true;
	if( deviceThreadHandle != NULL ){
		WaitForSingleObject(deviceThreadHandle, INFINITE);
	}
	deviceThreadHandle = NULL;

	pStartFunc();
	
	printf("\n\n\nEnd! \n");
	PressToContinue();
	pStopFunc();

	FreeLibrary(DllInstance);
}

DWORD WINAPI ThreadDevice (LPVOID pArg)
{
	DeviceValues dValues;
	ReadDeviceFunc pReadDevice = (ReadDeviceFunc)pArg;

	while( !sStopVrpnThread )
	{
		pReadDevice( &dValues );
		//cout << "Angles (yaw, pitch, roll): " << dValues.yaw << ", " << dValues.pitch << ", " << dValues.roll << " Firing_0: " << dValues.isButtonPress0 << endl;
		cout << "Buttons: " << dValues.buttons << " Angles (yaw, pitch, roll): " << dValues.yaw << ", " << dValues.pitch << ", " << dValues.roll << " Deltas (X, Y, Z): " << dValues.deltaX << ", " << dValues.deltaY << ", " << dValues.deltaZ << endl;
		Sleep((DWORD)1);
	}

	return 0;
}