/***************************************************************/
//
//
//		DirectX	[ gamepad.cpp ]
//
//											Author	kazuki tanaka
//											Date	2016 11/21
/*---------------------------------------------------------------
■Update : 2016/11/21
			gamepad.cppの作成

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

#include "gamepad.h"

#ifdef _DEBUG
#include <stdio.h>
#endif	// _DEGUG

/*---------------------------------------------------------------
	マクロ定義
---------------------------------------------------------------*/

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

/*---------------------------------------------------------------
	スタティックメンバ変数の初期化
---------------------------------------------------------------*/



// CInputGamepadコンストラスタ
CInputGamepad::CInputGamepad( )
	: CInput( CInput::TYPE_JOYPAD )
{

	// 各ワークのクリア
	ZeroMemory( &dijs,           sizeof dijs );
	ZeroMemory( &setDijs,        sizeof dijs );
	ZeroMemory( &dijsTrig,       sizeof dijs );
	ZeroMemory( stateTrigger,   sizeof (BYTE)*PAD_KEY_MAX );
	ZeroMemory( stateRelease,   sizeof (BYTE)*PAD_KEY_MAX );
	ZeroMemory( stateRepeat,    sizeof (BYTE)*PAD_KEY_MAX );
	ZeroMemory( stateRepeatCnt, sizeof (int)*PAD_KEY_MAX );

}

// CInputGamepadデストラスタ
CInputGamepad::~CInputGamepad( )
{

	// Do Nothing!!

}

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

// ジョイスティックの初期化処理
HRESULT CInputGamepad::Init( HINSTANCE hInstance, HWND hWnd )
{

	HRESULT hr;

	// 入力処理の初期化
	if(FAILED( CInput::Init( hInstance, hWnd ) ))
	{
		#ifdef _DEBUG
		MessageBox(hWnd, "DirectInputオブジェクトが作成出来ませんでした！", "警告！", MB_ICONWARNING);
		#endif	// _DEBUG
		return E_FAIL;
	}

	// デバイスオブジェクトを作成
	hr = CInput::pDirectInput->CreateDevice(GUID_Joystick, &pInputDevice, NULL);
	if(FAILED(hr) || pInputDevice == NULL)
	{
		MessageBox(hWnd, "ジョイスティックがねぇ！", "警告！", MB_ICONWARNING);
		return hr;
	}

	// データフォーマットを設定
	hr = pInputDevice->SetDataFormat(&c_dfDIJoystick2);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックのデータフォーマットを設定できませんでした。", "警告！", MB_ICONWARNING);
		return hr;
	}

	// 協調モードを設定（フォアグラウンド＆非排他モード）
	hr = pInputDevice->SetCooperativeLevel(hWnd, (DISCL_FOREGROUND | DISCL_NONEXCLUSIVE));
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックの協調モードを設定できませんでした。", "警告！", MB_ICONWARNING);
		return hr;
	}

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

	// デバイスからデータを取得
	hr =  pInputDevice ->GetDeviceState( sizeof( DIJOYSTATE2 ), &dijs );
	if( SUCCEEDED( hr )){

		// 値の初期化
		setDijs = dijs;
	}

	return hr;

}

// ジョイスティック入力処理の開放
void CInputGamepad::Uninit( void )
{
	// 入力処理の開放
	CInput::Uninit();
}

// ジョイスティックの更新処理
void CInputGamepad::Update( void )
{

	if(!pInputDevice)
	{
		return;
	}

	DIJOYSTATE2 currentDijs = { };


	// デバイスからデータを取得
	if(SUCCEEDED( pInputDevice->GetDeviceState(sizeof(DIJOYSTATE2), &currentDijs )))
	{

		// 値の初期化
		//currentDijs.lX -= setDijs.lX;
		//currentDijs.lY -= setDijs.lY;
		//currentDijs.lZ -= setDijs.lZ;

		for(int nCnKey = 0; nCnKey < PAD_KEY_MAX; nCnKey++)
		{
			
			// キートリガーリリース情報の作成
			stateTrigger[nCnKey]=( dijs.rgbButtons[nCnKey] ^ currentDijs.rgbButtons[nCnKey]) & currentDijs.rgbButtons[nCnKey];

			stateRelease[nCnKey]=( dijs.rgbButtons[nCnKey] ^ currentDijs.rgbButtons[nCnKey]) & dijs.rgbButtons[nCnKey];

			// キーリピート情報の生成
			if( currentDijs.rgbButtons[nCnKey] & 0x80 ){			//不具合起きた場合, if( dijs.rgbButtons[nCnKey] & 0x80 )
				if( stateRepeatCnt[nCnKey] < LIMIT_COUNT_REPEAT){
					stateRepeatCnt[nCnKey]++;
					if( stateRepeatCnt[nCnKey]==1){
					//if( g_dijsRepeatCnt[nCnKey]==1 || g_dijsRepeatCnt[nCnKey]>=LIMIT_COUNT_REPEAT ){

						stateRepeat[nCnKey]=currentDijs.rgbButtons[nCnKey];
		
					}
					else{
						
						stateRepeat[nCnKey] = 0 ;

					}
				}
			}
			else{
			
				stateRepeat[nCnKey]=0;
				stateRepeatCnt[nCnKey]=0;

			}

			// キープレス情報を保存
			//g_dijs.rgbButtons[nCnKey] = dijs.rgbButtons[nCnKey];

		}

		// 特殊キートリガー情報の取得
		dijsTrig.lX = ( dijs.lX ^ currentDijs.lX ) & currentDijs.lX;
		dijsTrig.lY = ( dijs.lY ^ currentDijs.lY ) & currentDijs.lY;
		dijsTrig.lZ = ( dijs.lZ ^ currentDijs.lZ ) & currentDijs.lZ;

		// キープレス情報を保存
		dijs = currentDijs;

	}
	else{
		// ゲームパッドへのアクセス権を取得
		pInputDevice ->Acquire( );
	}

}

// ジョイスティックデータ取得(プレス)
bool CInputGamepad::GetKeyPress(int nKey)
{
	return ( dijs.rgbButtons[ nKey ] & 0x80) ? TRUE: FALSE;
}

// ジョイスティックデータ取得(トリガー)
bool CInputGamepad::GetKeyTrigger(int nKey)
{
	return (stateTrigger[nKey] & 0x80) ? TRUE: FALSE;
}

// ジョイスティックデータ取得(リリース)
bool CInputGamepad::GetKeyRelease(int nKey)
{
	return (stateRelease[nKey] & 0x80) ? TRUE: FALSE;
}

// ジョイスティックデータ取得(リピート)
bool CInputGamepad::GetKeyRepeat(int nKey)
{
	return (stateRepeat[nKey] & 0x80) ? TRUE: FALSE;
}

// ジョイスティックデータ削除(トリガー)
void CInputGamepad::FlushKeyTrigger(int nKey)
{
	stateTrigger[nKey] = 0;
}

// ジョイスティック↑ボタンの取得
bool CInputGamepad::GetGamepadUp( void )
{
	return ( dijs.lY < 0 ) ? true: false; 
}

// ジョイスティック↓ボタンの取得
bool CInputGamepad::GetGamepadDown( void )
{
	return ( dijs.lY > 0 ) ? true: false; 
}

// ジョイスティック←ボタンの取得
bool CInputGamepad::GetGamepadLeft( void )
{
	return ( dijs.lX < 0 ) ? true: false; 
}

// ジョイスティック→ボタンの取得
bool CInputGamepad::GetGamepadRight( void )
{
	return ( dijs.lX > 0 ) ? true: false; 
}

// ジョイスティック↑ボタンの取得
bool CInputGamepad::GetGamepadUpTrigger( void )
{
	return ( dijsTrig.lY < 0 ) ? true: false; 
}

// ジョイスティック↓ボタンの取得
bool CInputGamepad::GetGamepadDownTrigger( void )
{
	return ( dijsTrig.lY > 0 ) ? true: false; 
}

// ジョイスティック←ボタンの取得
bool CInputGamepad::GetGamepadLeftTrigger( void )
{
	return ( dijsTrig.lX < 0 ) ? true: false; 
}

// ジョイスティック→ボタンの取得
bool CInputGamepad::GetGamepadRightTrigger( void )
{
	return ( dijsTrig.lX > 0 ) ? true: false; 
}



