/***************************************************************/
//
//
//		DirectX	[ mouse.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 2/15
/*---------------------------------------------------------------
■Update : 2017/2/15
			mouse.cppの作成

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/


//#include <Windows.h>
//#include <stdio.h>
//#include <d3dx9.h>

#include <Windows.h>
#include <stdio.h>

#include "system_component.h"
#include "mouse.h"
#include "window.h"
#include "game_manager.h"

//#pragma comment (lib,"d3d9.lib")
//#pragma comment (lib,"d3dx9.lib")
//#pragma comment (lib,"dxguid.lib")


/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/

#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }


/*---------------------------------------------------------------
	Const Number Difinition
---------------------------------------------------------------*/	

#define	NUM_KEY_MAX			( 8 )	// キーの最大数

#define	LIMIT_COUNT_REPEAT	( 20 )	// リピートカウントリミッター

/*----------------------------------------------------------------
	static member variable Initialize 
----------------------------------------------------------------*/

InputMouse* InputMouse::pMouse[ MOUSE_MAX ] = { };



// InputMouse Constructor
InputMouse::InputMouse( )
	: CInput( CInput::TYPE_MOUSE )
{

	// Member Clear Process
	ZeroMemory( &state,   sizeof(state) );
	ZeroMemory( &trigger, sizeof(trigger) );
	ZeroMemory( &release, sizeof(release) );
	pos.x = 0;
	pos.y = 0;

	// Registration Class( Mouse )
	for( int index = 0; index < MOUSE_MAX; index++ ){
		if( pMouse[index] == NULL ){
			pMouse[index] = this;
			myNumber = index;
			break;
		}
	}


}

// InputMouse Destructor
InputMouse::~InputMouse( )
{

	// Do Nothing!!

}

// InputMouse Create Instance
InputMouse* InputMouse::Create( void )
{
	
	// Create Class Instance
	InputMouse* pObject;
	pObject = new InputMouse;
	
	return pObject;
	
}

// InputMouse Access Outside Function
InputMouse* InputMouse::Access( const int index )
{
	
	// Return InputMouse Class
	return pMouse[ index ];
	
}

// InputMouse Initialize
HRESULT InputMouse::Init( HINSTANCE hInstance, HWND hWnd )
{

	// Initialize Process
	HRESULT hr = E_FAIL;

	// エラーメッセージ用CHARSET
	#ifdef _DEBUG
	const char WARNING[ ] = "DEVICE ERROR !";
	char ERROR_MESSAGE[ 256 ] = { };
	#endif	// _DEBUG

	// 入力処理の初期化
	CInput::Init( hInstance, hWnd );					// 複製生成しないようのインプットデバイス作成関数

	// デバイスの作成
	hr = CInput::pDirectInput ->CreateDevice(GUID_SysMouse, &pInputDevice, NULL );
	if( FAILED(hr) || pInputDevice == NULL) {

		#ifdef _DEBUG
		sprintf( ERROR_MESSAGE, " NOT FIND MOUSE！ error_code = 0x%x ", hr );
		MessageBox(hWnd, ERROR_MESSAGE, WARNING, MB_ICONWARNING | MB_OK );
		#endif	// _DEBUG
		return E_FAIL;
	}

	// データフォーマットを設定
	hr = pInputDevice->SetDataFormat(&c_dfDIMouse2);
	if( FAILED( hr )){

		#ifdef _DEBUG
		sprintf( ERROR_MESSAGE, " DONT SETTING MOUSE DATA FORMAT ! error_code = 0x%x ", hr );
		MessageBox(hWnd, ERROR_MESSAGE, WARNING, MB_ICONWARNING | MB_OK );
		#endif	// _DEBUG
		return E_FAIL;
	}

	// 協調モードを設定（フォアグラウンド＆非排他モード）
	hr = pInputDevice->SetCooperativeLevel(hWnd, (DISCL_FOREGROUND | DISCL_NONEXCLUSIVE ));
	if( FAILED( hr )){

		#ifdef _DEBUG
		sprintf( ERROR_MESSAGE, " DONT SETTING MOUSE DATA FORMAT ! error_code = 0x%x ", hr );
		MessageBox(hWnd, ERROR_MESSAGE, WARNING, MB_ICONWARNING | MB_OK );
		#endif	// _DEBUG
		return E_FAIL;
	}

	// デバイスの設定
	DIPROPDWORD dipdw;
	
	dipdw.diph.dwSize = sizeof(dipdw);
	dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
	dipdw.diph.dwObj = 0;
	dipdw.diph.dwHow = DIPH_DEVICE;
	//dipdw.dwData = DIDROPAXISMODE_REL;

	// マウスへのアクセス権を獲得(入力制御開始)
	if( FAILED( pInputDevice ->Poll( ))){
		pInputDevice->Acquire( );
	}

	return hr;

}

// InputMouse Uninitialize
void InputMouse::Uninit( void )
{

	// Uninitialize Process
	CInput::Uninit( );

}

// InputMouse Update
void InputMouse::Update( void )
{

	// Update Process
	DIMOUSESTATE2 current = {};

	// デバイス確認
	if( !pInputDevice ){
		return;
	}

	// デバイスからデータを取得
	if( SUCCEEDED( pInputDevice->GetDeviceState( sizeof(current), &current ))){
	
		trigger.lX = (state.lX ^  current.lX) & current.lX;
		trigger.lY = (state.lY ^  current.lY) & current.lY;
		trigger.lZ = (state.lZ ^  current.lZ) & current.lZ;

		release.lX = (state.lX ^  current.lX) & state.lX;
		release.lY = (state.lY ^  current.lY) & state.lY;
		release.lZ = (state.lZ ^  current.lZ) & state.lZ;

		for( int key = 0; key < 8; key++ ){
		
			trigger.rgbButtons[key] = (state.rgbButtons[key] ^  current.rgbButtons[key]) & current.rgbButtons[key];
			release.rgbButtons[key] = (state.rgbButtons[key] ^  current.rgbButtons[key]) & state.rgbButtons[key];
		}

		// Update Status
		state = current;

		// Get ScreenCoord
		POINT point;
		GetCursorPos( &point );
		ScreenToClient( Window::GetWindowHandle( ), &point );
		pos = Vector2( (float)point.x, (float)point.y );

	}else{
	
		pInputDevice->Acquire( );
	}

}

// InputMouse Release Class All
void InputMouse::ReleaseAll( void )
{

	// Release InputMouse All
	for( int index = 0; index < MOUSE_MAX; index ++ ){
		if( pMouse[ index ] ){

			pMouse[ index ] ->Uninit( );
			SAFE_DELETE( pMouse[ index ] )
		}
	}


}

// InputMouse Update Class All
void InputMouse::UpdateAll( void )
{

	// Update InputMouse All
	for( int index = 0; index < MOUSE_MAX; index ++ ){
		if( pMouse[ index ] != NULL ){

			pMouse[ index ] ->Update( );
		}
	}


}

// マウスのプレス状態を取得
bool InputMouse::GetPress( const int& key )
{
	return (state.rgbButtons[key] & 0x80) ? true: false;
}

// マウスのトリガー状態を取得
bool InputMouse::GetTrigger( const int& key )
{
	return (trigger.rgbButtons[key] & 0x80) ? true: false;
}

// マウスのリリ−ス状態を取得
bool InputMouse::GetRelease( const int& key )
{
	return (release.rgbButtons[key] & 0x80) ? true: false;
}

// マウスの座標取得
long InputMouse::GetAxisX(void)
{
	return state.lX;
}

// マウスの座標取得
LONG InputMouse::GetAxisY( void )
{
	return state.lY;
}

// マウスの座標取得
LONG InputMouse::GetAxisZ( void )
{
	return state.lZ;
}











