#include "Navigation3D.h"
#include <exception>

/*
 * @ 初始化3D鼠标
 * @ hWnd:   窗口句柄
 * @ Return: 是否初始化完成
 */
BOOL init_3D_Mouse(HWND hWnd)
{
	try
	{
		if (SiInitialize() != SPW_NO_ERROR)   //init the 3DxWare input library
		{
			return FALSE;
		}
		SiOpenData oData;
		SiOpenWinInit(&oData, hWnd);

		device = SiOpen("Navigation3D00", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
		if (device == NULL)
		{
			SiTerminate();
			return FALSE;
		}

		if (SiGrabDevice(device, TRUE) != SPW_NO_ERROR)
		{
			SiTerminate();
			return FALSE;
		}

		WM_3DMOUSE = RegisterWindowMessage(L"SpaceWareMessage00");
		if (WM_3DMOUSE == 0)
		{
			return FALSE;
		}

		return TRUE;
	}
	catch (const std::exception&)
	{
		return FALSE;
	}
}

/*
 * @ 3D鼠标是否完成初始化
 * @ Return: 是否初始化完成
 */
BOOL is_init_3D_Mouse()
{
	try
	{
		if (device == NULL || WM_3DMOUSE == 0)
			return FALSE;

		SPWbool result = SiIsInitialized();
		if (result != TRUE)
			return FALSE;

		return TRUE;
	}
	catch (const std::exception&)
	{
		return FALSE;
	}
}

/*
 * @ 销毁3D鼠标
 */
void dispose_3D_Mouse()
{
	try
	{
		SiTerminate();

		device = NULL;
		WM_3DMOUSE = 0;
	}
	catch (const std::exception&)
	{

	}
}

/*
 * 处理3D鼠标消息
 */
ThreeDMouseData* on_message_3D_Mouse(WPARAM wParam, LPARAM lParam)
{
	try
	{
		ThreeDMouseData* data = new ThreeDMouseData();
		data->result = 0;
		data->tx = 0;
		data->ty = 0;
		data->tz = 0;
		data->rx = 0;
		data->ry = 0;
		data->rz = 0;

		int            num;      /* number of button returned */
		SiSpwEvent     Event;    /* 3DxWare Event */
		SiGetEventData EData;    /* 3DxWare Event Data */

		/* init Window platform specific data for a call to SiGetEvent */
		SiGetEventWinInit(&EData, WM_3DMOUSE, wParam, lParam);

		/* check whether msg was a 3D mouse event and process it */
		if (SiGetEvent(device, 0, &EData, &Event) == SI_IS_EVENT)
		{
			switch (Event.type)
			{
			case SI_MOTION_EVENT:
				data->result = 1;
				data->tx = Event.u.spwData.mData[SI_TX];
				data->ty = Event.u.spwData.mData[SI_TY];
				data->tz = Event.u.spwData.mData[SI_TZ];
				data->rx = Event.u.spwData.mData[SI_RX];
				data->ry = Event.u.spwData.mData[SI_RY];
				data->rz = Event.u.spwData.mData[SI_RZ];

				break;

			case SI_ZERO_EVENT:
				data->result = 1;
				data->tx = 0;
				data->ty = 0;
				data->tz = 0;
				data->rx = 0;
				data->ry = 0;
				data->rz = 0;

				break;

			case  SI_BUTTON_EVENT:

				break;
			} /* end switch */
		} /* end SiGetEvent */
		return (data);
	}
	catch (const std::exception&)
	{
		return NULL;
	}
}

/*
 * 销毁3D鼠标数据
 * @ data : 3D鼠标数据
 */
void dispose_3D_Mouse_data(ThreeDMouseData* data)
{
	try
	{
		delete data;
	}
	catch (const std::exception&)
	{

	}
}