#include"CSingleWindowAppWindows.h"
#include"../../auxiliary/CString.h"
#include"../../auxiliary/Windows/CShell.h"
#include"../../auxiliary/Debug/CWarning.h"
#include"../../auxiliary/Debug/CAssert.h"
#include"../../auxiliary/Debug/CException.h"
#include"../../Graphic/Core/Driver/Windows/CFontDriverWindows.h"
#include"CSingleWindowMessageImpl1.h"


namespace Maid
{

const APPCONFIG& IGameThread::GetAppConfig()
{
	return m_Config;
}


void	IGameThread::OnSetup()
{
	m_Config.Graphic.Screen = APPCONFIG::GRAPHIC::SCREEN_WINDOW;
	m_Config.Graphic.Size = SIZE2DI(800,600);
	m_Config.Graphic.RefreshRate = 60;
	m_Config.Graphic.IsSoftTnL = false;
	m_Config.Graphic.IsWaitVSync = true;
	m_Config.Graphic.IsAspectLock = true;
	m_Config.Graphic.WindowCaption = MAIDTEXT("window");

	m_Config.Sound.SamplesPerSec = 44100;
	m_Config.Sound.BitsPerSample = 16;
	m_Config.Sound.Channels = 2;

	m_IsExitGame = false;
	OnLocalSetup( m_Config );
}

void	IGameThread::OnBegin( const BEGINPARAM& param )
{

	OnLocalBegin(param);
}

void	IGameThread::OnLoop()
{
	OnLocalLoop();
}

void	IGameThread::OnEnd()
{
	OnLocalEnd();
}


void IGameThread::OnButtonClose()
{
	OnExitGame();
}

void IGameThread::OnButtonMaximize() 
{
}

void IGameThread::OnDrawWindow() { }
void IGameThread::OnIMEResult( const mstring& str ) { }
void IGameThread::OnCharCode( unt32 code ) { }
void IGameThread::OnActivate( bool IsActive ) { }





CSingleWindowAppWindows* IGameThread::GetFrameWork()
{
	return 	static_cast<CSingleWindowAppWindows*>(IApplicationWindows::GetInstance());
}


void IGameThread::OnNextFrame( CGraphic& gra )
{
	RETURNMESSAGEQUE ret;

	gra.NextFrame();
	GetFrameWork()->OnNextFrame(ret);
	gra.OnReturnMessage(ret);
}

bool IGameThread::IsExitGame()
{
	return m_IsExitGame;
}

void IGameThread::OnExitGame()
{
	m_IsExitGame = true;
}













void CSingleWindowAppWindows::OnNextFrame( RETURNMESSAGEQUE& ret )
{
	while( true )
	{
		CThreadMutexLocker Lock(m_MessageMutex);

		CGraphic::FRAMEINFO* pInfo = &m_FrameInfo;

		if( !m_IsFrameUpdating )
		{
			//	描画が終わっていたら、キューを交換する
			m_GraphicCore.SwapRenderMessage( pInfo->que );
		}else
		{
			//	終わっていなくても、強制実行命令が出ている場合は待つ
			if( pInfo->IsForce ) { ::Sleep(0); continue; }
		}

		ret.swap(m_ReturnMessageQue);
		pInfo->que.resize(0);
		pInfo->IsForce = false;

		m_IsFrameUpdating = true;
		break;
	}
}


void CSingleWindowAppWindows::ExecuteWindowMessage()
{
	if( m_pGame.get()==NULL ) { return ; }

	SINGLEWINDOWMESSAGEQUE que;

	{
		CThreadMutexLocker Lock(m_MessageMutex);
		m_WindowMessageQue.swap( que );
	}


	for( int i=0; i<(int)que.size(); ++i )
	{
		switch( que[i]->Message )
		{
		case SingleWindowMessage::Base::PUSHCLOSEBUTTON: { m_pGame->OnButtonClose(); }break;
		case SingleWindowMessage::Base::PUSHMAXIMIZEBUTTON: { m_pGame->OnButtonMaximize(); }break;
		case SingleWindowMessage::Base::REDRAW: { m_pGame->OnDrawWindow(); }break;

		case SingleWindowMessage::Base::CHARACODE:
			{
				SingleWindowMessage::CharCode* p = static_cast<SingleWindowMessage::CharCode*>(que[i].get());
				m_pGame->OnCharCode( p->Code ); 
			}break;

		case SingleWindowMessage::Base::IMERESULT:
			{
				SingleWindowMessage::ImeResult* p = static_cast<SingleWindowMessage::ImeResult*>(que[i].get());
				m_pGame->OnIMEResult( p->Code ); 
			}break;

		case SingleWindowMessage::Base::ACTIVATE:
			{
				SingleWindowMessage::Activate* p = static_cast<SingleWindowMessage::Activate*>(que[i].get());
				m_pGame->OnActivate( p->IsActive ); 
			}break;
		}
	}
}

unt CSingleWindowAppWindows::ThreadFunction( volatile CThreadController::BRIGEDATA& brige )
{
	{
		m_pGame->OnSetup();

		if( m_pGame->IsExitGame() )
		{
			::SetEvent(m_hAppEvent);
			return 0; 
		}

	}

	::ResetEvent(m_hGameEvent);
	::SetEvent(m_hAppEvent);
	::WaitForSingleObject(m_hGameEvent, INFINITE);

	{
		IGameThread::BEGINPARAM	param;
		param.pInfo = &m_FrameInfo;
		param.pFontDriver = SPFONTDRIVER( new CFontDriverWindows() );
		param.pKeybordDriver  = m_pKeybordDriver;
		param.pMouseDriver    = m_pMouseDriver;
		param.pCharCodeDriver = m_pCharCodeDriver;
		param.pIMEDriver = m_pIMEDriver;

		m_pGame->OnBegin( param );
	}

	while( true )
	{
		if( brige.IsExit ) { break; }
		if( m_pGame->IsExitGame() ) { break; }

		ExecuteWindowMessage();
		m_pGame->OnLoop();
	}

	m_pGame->OnEnd();

	m_pGame.reset();

	RETURNMESSAGEQUE ret;

	OnNextFrame(ret);
	return 0;
}



}
