#include "StdAfx.h"
#include "keyboardagent.h"

cKeyboardAgent::cKeyboardAgent()
: mpDidKey(NULL)
{
	mDown = 0;
}

cKeyboardAgent::~cKeyboardAgent()
{
	Release();
}

/* ------------------------------------------------------------------
 * 함수이름 :	Create( HWND hWnd, LPDIRECTINPUT8 pdi )
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
HRESULT cKeyboardAgent::Create( HWND hWnd, LPDIRECTINPUT8 pDi )
{
	HRESULT hr;
	unsigned long coopFlags = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND | DISCL_NOWINKEY;

	hr = pDi->CreateDevice( GUID_SysKeyboard, &mpDidKey, NULL );
	hr |= mpDidKey->SetDataFormat( &c_dfDIKeyboard );
	hr |= mpDidKey->SetCooperativeLevel( hWnd, coopFlags );

	DIPROPDWORD dipdw;

	dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
	dipdw.diph.dwObj        = 0;
	dipdw.diph.dwHow        = DIPH_DEVICE;
	dipdw.dwData            = KEYBOARD_BUFFER;

	hr = mpDidKey->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );

	mpDidKey->Acquire();

	ClearKeyState();

	return hr;
}

/* ------------------------------------------------------------------
 * 함수이름 :	Release()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
void cKeyboardAgent::Release()
{
	if( mpDidKey )
		mpDidKey->Unacquire();

	SAFE_RELEASE( mpDidKey );
}


/* ------------------------------------------------------------------
 * 함수이름 :	UpdateKeyboardState()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
void cKeyboardAgent::UpdateKeyboardState()
{
	mDown = 0;
	HRESULT hr = E_FAIL;

	mBufferedKeys = KEYBOARD_BUFFER;

	hr = mpDidKey->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), mDidodKey, &mBufferedKeys, 0 );
	if( FAILED( hr ) )
	{
		do
		{
			hr = mpDidKey->Acquire();
		}
		while( hr == DIERR_INPUTLOST );

		ClearKeyState();
	}
	else
	{
		mBufferPos = mBufferedKeys;
	}
}

/* ------------------------------------------------------------------
 * 함수이름 :	StartGetKeyState()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
void cKeyboardAgent::StartGetKeyState()
{
	mBufferPos = 0;
}

/* ------------------------------------------------------------------
 * 함수이름 :	GetNextKeyState()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
bool cKeyboardAgent::GetNextKeyState()
{
	++mBufferPos;

	if( mBufferPos > mBufferedKeys )
	{
		return false;
	}

	///PressKey
	if( mDidodKey[mBufferPos-1].dwData & 0x80 )
	{
		mKeyPress[mDidodKey[mBufferPos-1].dwOfs] = true;
		mDown = mDidodKey[mBufferPos-1].dwOfs;
	}
	else
	{
		mKeyPress[mDidodKey[mBufferPos-1].dwOfs] = false;
		mDown = 0;
	}

	return true;
}

/* ------------------------------------------------------------------
 * 함수이름 :	GetKeyDown( unsigned long key )
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
bool cKeyboardAgent::GetKeyDown( unsigned long key )
{
	if( mBufferedKeys == 0 ) 
	{
		return false;
	}

	if( mBufferPos > mBufferedKeys || mBufferPos < 1 )
	{
		return false;
	}

	if( ( mDidodKey[mBufferPos-1].dwOfs == key ) && ( mDidodKey[mBufferPos-1].dwData & 0x80 ) )
	{
		return true;
	}

	return false;
}

/* ------------------------------------------------------------------
 * 함수이름 :	GetKeyUp( unsigned long key )
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
bool cKeyboardAgent::GetKeyUp( unsigned long key )
{
	if( mBufferedKeys == 0 ) 
	{
		return false;
	}

	if( mBufferPos > mBufferedKeys || mBufferPos < 1 )
	{
		return false;
	}

	assert( mBufferPos <= mBufferedKeys && mBufferPos > 0 );

	if( ( mDidodKey[mBufferPos-1].dwOfs == key ) && !( mDidodKey[mBufferPos-1].dwData & 0x80 ) )
	{
		return true;
	}

	return false;
}

/* ------------------------------------------------------------------
 * 함수이름 :	GetKeyPressed( unsigned long key )
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
bool cKeyboardAgent::GetKeyPressed( unsigned long key )
{
	return mKeyPress[key]? true:false;
}

/* ------------------------------------------------------------------
 * 함수이름 :	ClearKeyState()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
void cKeyboardAgent::ClearKeyState()
{
	mBufferedKeys	= 0;
	mBufferPos		= 1;
	mDown = 0;

	ZeroMemory( mKeyPress, sizeof( mKeyPress ) );
}

/* ------------------------------------------------------------------
 * 함수이름 :	IsEmptyKeyboardEvent()
 * 목    적 :	
 * 주의사항 :	
 * ------------------------------------------------------------------ */
bool cKeyboardAgent::IsEmptyKeyboardEvent()
{
	if( mBufferPos > mBufferedKeys )
	{
		return true;
	}

	return false;
}