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

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

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

#include "game_manager.h"
#include "keyboard.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	COUNT_WAIT_REPEAT	(20)	// リピート待ち時間

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

CInputKeyboard* CInputKeyboard::pInputKeyboard[ INPUTKEYBOARD_MAX ] = { };


// CInputKeyboardコンストラスタ
CInputKeyboard::CInputKeyboard( )
		: CInput( CInput::TYPE_KEYBOARD )
{


	// Member Clear Process
	ZeroMemory( m_aKeyState,          sizeof (BYTE)*NUM_KEY_MAX );
	ZeroMemory( m_aKeyStateTrigger,   sizeof (BYTE)*NUM_KEY_MAX );
	ZeroMemory( m_aKeyStateRelease,   sizeof (BYTE)*NUM_KEY_MAX );
	ZeroMemory( m_aKeyStateRepeat,    sizeof (BYTE)*NUM_KEY_MAX );
	ZeroMemory( m_aKeyStateRepeatCnt, sizeof (int)*NUM_KEY_MAX  );


	// Registration Class( InputKeyboard )
	for( int index = 0; index < INPUTKEYBOARD_MAX; index++ ){
		if( pInputKeyboard[index] == NULL ){
			pInputKeyboard[index] = this;
			myNumber = index;
			break;
		}
	}


}

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

	// Do Nothing!!

}

// CInputKeyboard Create Instance 
CInputKeyboard* CInputKeyboard::Create( const char* INPUTKEYBOARD_NAME )
{

	// Create Class Instance
	CInputKeyboard* pObject;
	pObject = new CInputKeyboard;

	// Setting Class Name for Access
	strcpy( pObject->inputName, INPUTKEYBOARD_NAME );


	return pObject;

}

// CInputKeyboard Access Outside Function  
CInputKeyboard* CInputKeyboard::Access( const char* INPUTKEYBOARD_NAME )
{

	// Search CInputKeyboard Class
	for( int index = 0; index < INPUTKEYBOARD_MAX; index ++ ){
		if( pInputKeyboard[index] != NULL ){
			if( strcmp( pInputKeyboard[index]->inputName, INPUTKEYBOARD_NAME ) == 0 ){

				return pInputKeyboard[index];
				break;
			}
		}
	}

	return 0;

}

// CInputKeyboard Access Outside Function  
CInputKeyboard* CInputKeyboard::Access( const int index )
{
	
	// Return CMouse Class
	return pInputKeyboard[ index ];
	
}

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

	// Release CInputKeyboard All
	for( int index = 0; index < INPUTKEYBOARD_MAX; index ++ ){
		if( pInputKeyboard[ index ] ){

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


}

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

	// Update CInputKeyboard All
	for( int index = 0; index < INPUTKEYBOARD_MAX; index ++ ){
		if( pInputKeyboard[ index ] != NULL ){

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


}




// キーボードの初期化処理
HRESULT CInputKeyboard::Init(HINSTANCE hInst, HWND hWnd)
{
	HRESULT hr;

	// 入力処理の初期化
	CInput::Init(hInst, hWnd);

	// デバイスオブジェクトを作成
	hr = pDirectInput->CreateDevice(GUID_SysKeyboard, &pInputDevice, NULL);
	if(FAILED(hr) || pInputDevice == NULL)
	{
		MessageBox(hWnd, "キーボードがねぇ！", "警告！", MB_ICONWARNING);
		return hr;
	}

	// データフォーマットを設定
	hr = pInputDevice->SetDataFormat(&c_dfDIKeyboard);
	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;
	}

	// m_pDIDeviceアクセス権を獲得(入力制御開始)
	pInputDevice->Acquire();

	return hr;
}

// キーボード入力処理の開放
void CInputKeyboard::Uninit(void)
{

	// 入力処理の開放
	CInput::Uninit( );

}

// キーボードの更新処理
void CInputKeyboard::Update(void)
{

	HRESULT hr;
	BYTE aKeyState[NUM_KEY_MAX];

	if(!pInputDevice){
		return;
	}

	// デバイスからデータを取得
	hr = pInputDevice->GetDeviceState(sizeof(aKeyState), aKeyState);
	if(SUCCEEDED(hr))
	{
		for(int nCntKey = 0; nCntKey < NUM_KEY_MAX; nCntKey++)
		{
			m_aKeyStateTrigger[nCntKey] = (m_aKeyState[nCntKey] ^ aKeyState[nCntKey]) & aKeyState[nCntKey];
			m_aKeyStateRelease[nCntKey] = (m_aKeyState[nCntKey] ^ aKeyState[nCntKey]) & ~aKeyState[nCntKey];
			m_aKeyStateRepeat[nCntKey] =   m_aKeyStateTrigger[nCntKey];

			if(aKeyState[nCntKey])
			{
				m_aKeyStateRepeatCnt[nCntKey]++;
				if(m_aKeyStateRepeatCnt[nCntKey] >= COUNT_WAIT_REPEAT)
				{
					m_aKeyStateRepeat[nCntKey] = aKeyState[nCntKey];
				}
			}
			else
			{
				m_aKeyStateRepeatCnt[nCntKey] = 0;
				m_aKeyStateRepeat[nCntKey] = 0;
			}

			m_aKeyState[nCntKey] = aKeyState[nCntKey];
		}
	}
	else
	{
		pInputDevice->Acquire();
	}
}

// キーボードデータ取得(プレス)
BOOL CInputKeyboard::GetKeyPress(int nKey)
{

	return (m_aKeyState[nKey] & 0x80) ? TRUE: FALSE;

}

// キーボードデータ取得(トリガー)
BOOL CInputKeyboard::GetKeyTrigger(int nKey)
{
	return (m_aKeyStateTrigger[nKey] & 0x80) ? TRUE: FALSE;
}

// キーボードデータ取得(リリース)
BOOL CInputKeyboard::GetKeyRelease(int nKey)
{
	return (m_aKeyStateRelease[nKey] & 0x80) ? TRUE: FALSE;
}

// キーボードデータ取得(リピート)
BOOL CInputKeyboard::GetKeyRepeat(int nKey)
{
	return (m_aKeyStateRepeat[nKey] & 0x80) ? TRUE: FALSE;
}

// キーボードデータ削除(トリガー)
void CInputKeyboard::FlushKeyTrigger(int nKey)
{
	m_aKeyStateTrigger[nKey] = 0;
}

