#include <windows.h>
#include "Graphic.h"


CGraphic*						g_pGraphic				= NULL;
const INT32						g_resourceArenaSize		= 8388608 * 4;

CGraphic::CGraphic()
{
	m_hWnd				= NULL;
	m_width				= 0;
	m_height			= 0;
	m_IsShowGrid		= true;

	m_pRuSwapChain		= NULL;
	m_pRuTimer			= NULL;
	m_pRuLightingTree	= NULL;
	m_pCamera			= NULL;
	m_pRuWidgetGrid		= NULL;
	m_pSystemFont		= NULL;
	m_pTexture			= NULL;

	memset(m_resourcePath, 0, sizeof(m_resourcePath));
}

CGraphic::~CGraphic()
{
	CRuFontChar::Shutdown();
	CTextureImage::Shutdown();
	

	SAFE_DELETE(m_pTexture);
	SAFE_DELETE(m_pRuTimer);
	ruSAFE_RELEASE( m_pRuWidgetGrid );

	IBaseSprite::Shutdown();

	ruSAFE_RELEASE(m_pRuSwapChain);
	SAFE_DELETE(m_pCamera);

	// 關閉引擎
	RuShutdown();
}

bool CGraphic::RuneDevInitialize(HWND hWnd, bool isWindowed, const char* ResourcePathStr )
{
	// 開啟引擎並保存回傳 SwapChain
//	if ( (m_pRuSwapChain = RuInitialize(hWnd, hWnd, g_resourceArenaSize)) == NULL )
//		return false;

	BOOL coreInitializeOK = RuInitialize_Core();

	// 開啟引擎並保存回傳 SwapChain
	if ( (m_pRuSwapChain = RuInitialize_D3D( hWnd, hWnd, g_resourceArenaSize )) == NULL )
		return false;

	BOOL sceneInitializeOK = RuInitialize_Scene( m_pRuSwapChain );

	SetResourcePath( ResourcePathStr );		

	// 建立主鏡頭
	m_pCamera = ruNEW CRuCamera;
	m_pCamera->SetCameraPosition( CRuVector3(0.0f, 10.0f, -30.0f) );	// 鏡頭所在位置
	m_pCamera->SetTargetPosition( CRuVector3(0.0f, 10.0f, 0.0f) );		// 鏡頭目的位置
	m_pCamera->SetCameraUpVector( CRuVector3(0.0f, 1.0f, 0.0f) );		// 鏡頭上方所朝方向

	// 貼圖初始化
	CTextureImage::Initialize();

	// 字型初始化
	CRuFontChar::Initialize(NULL);

	// 產生系統使用文字物件
	m_pSystemFont = CRuFontType::GetFontType("Arial", 16, ruFONTWEIGHT_BOLD, ruFONTOUTLINE_NORMAL);		

	IBaseSprite::Initialize();
	IBaseSprite::SetFontType( m_pSystemFont );

	m_pRuTimer = new CRuPerformanceTimer;
	m_pRuTimer->Initialize(0);
	m_pRuTimer->ElapsedTime();

	// 設定畫面解析度
	RECT rect;
	GetClientRect( hWnd, &rect );
	SetScreenSize( rect.right - rect.left, rect.bottom - rect.top, isWindowed );

	// 產生燈光樹
	m_pRuLightingTree = CreateLightingProp();	

	m_pRuWidgetGrid = new CRuEntity_Widget_Grid;
	if ( m_pRuWidgetGrid )
	{
		m_pRuWidgetGrid->SetGridProperties( CRuVector3(1.0f, 0.0f, 0.0f), CRuVector3(0.0f, 1.0f, 0.0f), CRuVector3(0.0f, 0.0f, 0.0f), 150.0f, 5.0f );
	}

	return true;
}

void CGraphic::SetScreenSize(int width, int height, bool isWindowed)
{
	if ( m_width != width || m_height != height )
	{		
		m_width = width;
		m_height = height;

		// 更新畫面解析度
		if ( !RuSetResolution( m_pRuSwapChain, (UINT32)m_width, (UINT32)m_height, false ) )
			return;

		// 設定鏡頭視角
		if ( m_pCamera )
			m_pCamera->SetPerspectiveProjectionFOV( 1.0f, 2500.0f, 1.308997f, (float)m_width / m_height );
	}
}

void CGraphic::SetResourcePath(const char* pathStr)
{
	memset( m_resourcePath, 0, sizeof(m_resourcePath) );	
	if ( pathStr && strlen(pathStr) > 0 )
	{
		strcpy( m_resourcePath, pathStr );
		int len = strlen( m_resourcePath );
		if ( m_resourcePath[len-1] == '\\' )
			m_resourcePath[len-1] = 0;
	}

	g_ruResourceManager->SetRootDirectory( m_resourcePath );

	g_ruResourceManager->LoadPackageFile("fdb\\other.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\cache.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\interface.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\model.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\motion.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\music.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\sound.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture0.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture1.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture2.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture3.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture4.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture5.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture6.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture7.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture8.fdb");
	g_ruResourceManager->LoadPackageFile("fdb\\texture9.fdb");


}

// --------------------------------------------------------------------------------------
void CGraphic::SetTextureImageFile(const char* filename)
{
	if (m_pTexture == NULL)
		m_pTexture = new CTextureImage;
	m_pTexture->SetFileName(filename);
}

// --------------------------------------------------------------------------------------
const char*	CGraphic::GetFullFilePath(const char* fileStr)
{
	static int count = 0;
	static char tmpStr[5][MAX_PATH];

	count++;
	if ( count >= 5 )
		count = 0;

	if ( m_resourcePath[0] == 0 )
		strcpy( tmpStr[count], fileStr );
	else
		sprintf( tmpStr[count], "%s\\%s", m_resourcePath, fileStr );

	return tmpStr[count];
}

// --------------------------------------------------------------------------------------
void CGraphic::Update()
{
	float time		= m_pRuTimer->GetTime() / 1000.0f;
	m_elapsedTime	= time - m_frameTime;
	m_frameTime		= time;

	g_ruFunctionSchedule->Update();
	
	IBaseSprite::UpdateAll( m_elapsedTime );
	if ( m_pRuWidgetGrid )
		m_pRuWidgetGrid->Update( m_elapsedTime );

	// 開始繪製
	if( g_ruEngine->BeginScene() )
	{		
		// 開始3D繪圖
		//g_ruDefaultRenderContext->Scene_Begin();		
		g_ruRenderer->Begin();

		// 選取主要swap chain為繪製平面
		// m_pRuSwapChain->SelectRenderTarget();

		// 選用主鏡頭
		g_ruDefaultRenderContext->Camera_Push( m_pCamera );
		g_ruUIRenderer->Camera_Push( m_pCamera );

		// 設定主要swap chain為輸出目標
//		g_ruDefaultRenderContext->Scene_SetRenderTarget( m_pRuSwapChain, 1000, RUCLEAR_TARGET | RUCLEAR_ZBUFFER | RUCLEAR_STENCIL, 0x00000000, 1.0f, 0);
//		g_ruEngine->Clear( RUCLEAR_TARGET, 0x00000000, 0.0f, 0 );

		// 更新燈光樹
		m_pRuLightingTree->Update( m_elapsedTime );

		// 設定反射光顏色
		g_ruRenderer->GetDefaultParameterBlock().SetParameter(ruPARAMTYPE_LIGHT_SPECULAR_COLOR, RUCOLOR_ARGB(0, 0, 0, 0));

		// 設定反射光方向
//		CRuVector3 unitDirection(0.0f, 1.0f, 0.0f);
//		g_ruDefaultRenderContext->GetShaderParameterBlock()->SetParameter(ruPARAMTYPE_LIGHT_SPECULAR_DIR, (DWORD) &unitDirection);

		// 設定要使用的燈光樹
		g_ruRenderer->SetLightingProp( m_pRuLightingTree );

		if ( m_pRuWidgetGrid && m_IsShowGrid )
			g_ruDefaultRenderContext->Submit( m_pRuWidgetGrid );

		// 繪出角色
		IBaseSprite::RenderAll();

		// 結束3D繪圖
		//g_ruDefaultRenderContext->Scene_End();		
		//g_ruDefaultRenderContext->End();

		//if ( g_ruDefaultRenderContext->Ru2D_Begin() )
		//{
            if( m_pTexture != NULL )
			    m_pTexture->Draw(0, 0, ALPHA_MODE_BLEND, 0xFFFFFFFF);

			char fpsStr[1024];
			sprintf(fpsStr, "fps: %.2f", m_fps);

			WCHAR tmpStr[1024];
			MultiByteToWideChar(CP_ACP, 0, fpsStr, -1, tmpStr, 1023);

			CRuFontChar::DrawText(m_pSystemFont, 100, 0, 0xFFFFFF00, tmpStr);

			//g_ruDefaultRenderContext->Ru2D_End();						// 結束2D繪圖
			g_ruUIRenderer->SetScissorRect(NULL);
		//}

		g_ruRenderer->End();

		// 結束繪製
		if( !g_ruEngine->EndScene() )
		{
		}
	}	

	// Present主要swap chain
	m_pRuSwapChain->Present();	

	// 輸出視窗資訊
	{
		static float oldTime;
		static float frame;

		// 計算每秒張數
		if ( m_frameTime - oldTime >= 1.0f )
		{
			m_fps		= frame / (m_frameTime - oldTime);			
			oldTime		= m_frameTime;
			frame		= 0.0f;
		}
		frame++;
	}
}

// ------------------------------------------------------------------------------------------------
// 暫時替代性世界光源
CRuFrame* CGraphic::CreateLightingProp()
{
	// 設定燈光樹
	CRuFrame *lightingTree = ruNEW CRuFrame();

	CRuEntity_Light *lightEntity0 = ruNEW CRuEntity_Light();
	CRuEntity_Light *lightEntity1 = ruNEW CRuEntity_Light();
	CRuEntity_Light *lightEntity2 = ruNEW CRuEntity_Light();
	CRuEntity_Light *lightEntity3 = ruNEW CRuEntity_Light();
	CRuEntity_Light *lightEntity4 = ruNEW CRuEntity_Light();

	CRuVector3 direction0(0.5f, -0.3f, 0.5f);
	CRuVector3 direction1(0.0f, 0.0f, 1.0f);
	CRuVector3 direction2(0.0f, 0.0f, -1.0f);
	CRuVector3 direction3(1.0f, 0.0f, 0.0f);
	CRuVector3 direction4(-1.0f, 0.0f, 0.0f);

	direction0.Normalize();
	direction1.Normalize();
	direction2.Normalize();
	direction3.Normalize();
	direction4.Normalize();

	lightEntity0->SetLightType(ruLIGHTTYPE_DIRECTIONAL);
	lightEntity0->SetDirection(direction0);
	lightEntity0->SetDiffuse(CRuColor4(1.0f, 249.0f/255.0f, 218.0f/255.0f, 183.0f/255.0f));
	lightEntity0->Update(0.0f);

	lightEntity1->SetLightType(ruLIGHTTYPE_DIRECTIONAL);
	lightEntity1->SetDirection(direction1);
	lightEntity1->SetDiffuse(CRuColor4(1.0f, 51.0f/255.0f, 54.0f/255.0f, 94.0f/255.0f));
	lightEntity1->Update(0.0f);

	lightEntity2->SetLightType(ruLIGHTTYPE_DIRECTIONAL);
	lightEntity2->SetDirection(direction2);
	lightEntity2->SetDiffuse(CRuColor4(1.0f, 51.0f/255.0f, 54.0f/255.0f, 94.0f/255.0f));
	lightEntity2->Update(0.0f);

	lightEntity3->SetLightType(ruLIGHTTYPE_DIRECTIONAL);
	lightEntity3->SetDirection(direction3);
	lightEntity3->SetDiffuse(CRuColor4(1.0f, 51.0f/255.0f, 54.0f/255.0f, 94.0f/255.0f));
	lightEntity3->Update(0.0f);

	lightEntity4->SetLightType(ruLIGHTTYPE_DIRECTIONAL);
	lightEntity4->SetDirection(direction4);
	lightEntity4->SetDiffuse(CRuColor4(1.0f, 51.0f/255.0f, 54.0f/255.0f, 94.0f/255.0f));
	lightEntity4->Update(0.0f);

	lightingTree->AddChild(lightEntity0);
	lightingTree->AddChild(lightEntity1);
	lightingTree->AddChild(lightEntity2);
	lightingTree->AddChild(lightEntity3);
	lightingTree->AddChild(lightEntity4);

	return lightingTree;
}


