#include"CKeybord.h"
#include"../Auxiliary/Debug/CAssert.h"
#include"../Auxiliary/CString.h"


namespace Maid
{
	/*!
	 	@class	CKeybord CKeybord.h
	 	@brief	キーボード入力を管理するクラス
	 */
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 */
CKeybord::CKeybord()
{

}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デストラクタ
/*!
 */
CKeybord::~CKeybord()
{
	if( m_pKeybordDriver.get()!=NULL ) { m_pKeybordDriver->Finalize(); }
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! キーボードの初期化
/*!
 	@param	pDriver	[i ]	新しく設定するドライバ
 */
void CKeybord::Initialize( const SPKEYBORDDRIVER& pKey, const SPCHARCODEDRIVER& pChar )
{
	m_pKeybordDriver  = pKey;
	m_pCharCodeDriver = pChar;

	m_ButtonList.resize( m_pKeybordDriver->GetButtonnMax() );
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 文字コードドライバからコールバックされる関数の設定
/*!
 	@param	Function	[i ]	関数
 */
void CKeybord::SetCharCodeFunction( const ICharCodeDriver::CHARCODEFUNCTION& Function )
{
	m_Function = Function;
}

void CKeybord::OnCharCode( unt32 code )
{
	if( !m_Function ) { return; }
	m_Function( code );
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! キーボードの状態を更新する
/*!
 	フレーム毎に１回呼び出すこと
 */
void CKeybord::Update()
{
	MySTL::vector<bool> KeyList(m_ButtonList.size());
	m_pKeybordDriver->IsDown(KeyList);

	for( int i=0; i<(int)KeyList.size(); ++i )
	{
		//	半角/全角　ボタンは無効にしておく
		//	OS側でＩＭＥのフックとかしててメンドイ
		if( i==0xE5 ) { continue; }

		const bool IsDown  = KeyList[i];
		BUTTONSTATE& state = m_ButtonList[i];

		if( IsDown )
		{
			state.DownCount++;	//	オーバーフローすることもあるけど・・・・いいやヾ(´▽｀*)ゝ
		}else
		{
			state.IsOut = state.DownCount!=0;
			state.DownCount = 0;
		}
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! キーボードの状態の初期化
/*!
 	ほかのウィンドウダイアログを出したときなどに、ボタンの状態がおかしくなるけーすがある
 	そんなときに呼び出してください。（通常はつかいません）
 */
void CKeybord::Flash()
{
	m_pKeybordDriver->Reset();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ボタンが押されているか調べる
/*!
 	@param	Index	[i ]	取得したいボタン
 
 	@return 押されているか？
 */
bool CKeybord::IsDown( unt08 Index ) const
{
	MAID_ASSERT( !(Index<m_ButtonList.size()), "ボタンの指定がおかしいです " << Index << " "<< m_ButtonList.size() );
	return m_ButtonList[Index].DownCount!=0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したボタンが押された瞬間か調べる
/*!
 	@param	Index	[i ]	取得したいボタン
 
 	@return 押されているか？
 */
bool CKeybord::IsIn( unt08 Index ) const
{
	MAID_ASSERT( !(Index<m_ButtonList.size()), "ボタンの指定がおかしいです " << Index << " "<< m_ButtonList.size() );
	return m_ButtonList[Index].DownCount==1;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したボタンが離された瞬間か調べる
/*!
 	@param	Index	[i ]	取得したいボタン
 
 	@return 押されているか？
 */
bool CKeybord::IsOut( unt08 Index ) const
{
	MAID_ASSERT( !(Index<m_ButtonList.size()), "ボタンの指定がおかしいです " << Index << " "<< m_ButtonList.size() );
	return m_ButtonList[Index].IsOut;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したボタンが押されて一定時間経過したか調べる
/*!
 	@param	Index	[i ]	取得したいボタン
 	@param	Frame	[i ]	リピート間隔
 
 	@return 押されているか？
 */
bool CKeybord::IsRepeat( unt08 Index, unt Frame  ) const
{
	MAID_ASSERT( !(Index<m_ButtonList.size()), "ボタンの指定がおかしいです " << Index << " "<< m_ButtonList.size() );
	return (m_ButtonList[Index].DownCount%Frame)==1;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したボタンが押されて一定時間経過したか調べる
/*!
 	@param	Index		[i ]	取得したいボタン
 	@param	Frame		[i ]	リピート間隔
 	@param	BeginFrame	[i ]	リピートチェックを開始する時間
 
 	@return 押されているか？
 */
bool CKeybord::IsRepeat( unt08 Index, unt Frame, unt BeginFrame  ) const
{
	MAID_ASSERT( !(Index<m_ButtonList.size()), "ボタンの指定がおかしいです " << Index << " "<< m_ButtonList.size() );

	const BUTTONSTATE& state = m_ButtonList[Index];

	if( state.DownCount<BeginFrame )
	{
		return state.DownCount==1;
	}

	return ((state.DownCount-BeginFrame)%Frame)==0;
}


}

