//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * プリズマティックアンブレラ実装
 * @author Junpee
 */

#include "Core/Utility/stdafx.h"
#include "Core/System/PrismaticUmbrella.h"
#include "Game/System/GameSystem.h"
#include "Core/Utility/Performance.h"
#include "Core/Utility/DebugHUD.h"

// インスタンス
PrismaticUmbrella* PrismaticUmbrella::instance_ = NULL;

//------------------------------------------------------------------------------
// プログラムエントリポイント
//------------------------------------------------------------------------------
// メイン関数
int WINAPI WinMain(
	HINSTANCE instance, HINSTANCE previousInstance, LPSTR command, int show){
	PrismaticUmbrella prismaticUmbrella(instance, command);
	return prismaticUmbrella.execute();
}
//------------------------------------------------------------------------------
// コンストラクタ
PrismaticUmbrella::PrismaticUmbrella(
	HINSTANCE instanceHandle, const String& command) :
	gameSystem_(NULL), instanceHandle_(instanceHandle), windowHandle_(0),
	name_("PrismaticUmbrella"), command_(command), fpsController_(NULL),
	drawFPSMeasurement_(NULL), gameFPSMeasurement_(NULL), 
//	windowWidth_(640), windowHeight_(480), startFullscreen_(false){
	windowWidth_(640), windowHeight_(480), startFullscreen_(true){
	::ShowCursor(false);///////////////////とりあえず
}
//------------------------------------------------------------------------------
// デストラクタ
PrismaticUmbrella::~PrismaticUmbrella(){
}
//------------------------------------------------------------------------------
// 実行
int PrismaticUmbrella::execute(){
	int result = 1;
	// 初期化
	if(initialize()){ result = mainLoop(); }
	// 後始末
	finalize();
	return result;
}
//------------------------------------------------------------------------------
// 初期化
//------------------------------------------------------------------------------
// 初期化
bool PrismaticUmbrella::initialize(){
	// グラフィックス初期化
	LampGraphics::initialize();
	// ウィンドウの初期化
	if(!initializeWindow()){ return false; }

	// デバッグヘッドアップディスプレイ初期化
	DebugHUD::initialize(windowHandle_);

	// Graphicsデバイス初期化
	GraphicsDeviceEnumeration* enumeration =
		GraphicsDeviceEnumeration::getInstance();
	// バックバッファを32bitカラーバッファ、24bit深度バッファにする
//	enumeration->setMinimumDepthBits(24);
//	enumeration->setMinimumBackBufferAlphaChannelBits(8);
	if(!LampGraphics::initializeDevice(windowHandle_, startFullscreen_)){
		return false;
	}
	// 初回背景クリア
	GraphicsDevice::getInstance()->clear(Color4c::gray);

	// LampInput初期化
	if(!LampInput::initialize(instanceHandle_, windowHandle_)){ return false; }

	// LampSound初期化
	if(!LampSound::initialize(windowHandle_)){ return false; }

	// FPSコントローラ初期化
	fpsController_ = new FPSController();

	// FPS計測初期化
	drawFPSMeasurement_ = new FPSMeasurement();
	gameFPSMeasurement_ = new FPSMeasurement();

	// ゲームシステム初期化
	gameSystem_ = new GameSystem();

	// インスタンスポインタ設定
	Assert(instance_ == NULL);
	instance_ = this;
	return true;
}
//------------------------------------------------------------------------------
// ウィンドウの初期化
bool PrismaticUmbrella::initializeWindow(){
	// ウィンドウパラメータ設定
	WindowCreator::CreateParameter parameter_;
	parameter_.windowName_ = name_;
	parameter_.instanceHandle_ = instanceHandle_;
	parameter_.windowProcedure_ = registrationWindowProcedure;
	parameter_.createWidth_ = windowWidth_;
	parameter_.createHeight_ = windowHeight_;
	// サイズ変更無効化
	parameter_.windowStyle_ ^= WS_THICKFRAME;
	parameter_.windowStyle_ ^= WS_MAXIMIZEBOX;

	// ウィンドウの作成
	windowHandle_ = WindowCreator::create(parameter_);
	if(windowHandle_ == NULL){ return false; }
	return true;
}
//------------------------------------------------------------------------------
// 後始末
//------------------------------------------------------------------------------
// 後始末
void PrismaticUmbrella::finalize(){
	// インスタンスポインタクリア
	instance_ = NULL;
	// ゲームシステム後始末
	SafeDelete(gameSystem_);
	// FPS計測後始末
	SafeDelete(gameFPSMeasurement_);
	SafeDelete(drawFPSMeasurement_);
	// FPSコントローラ後始末
	SafeDelete(fpsController_);
	// LampSoundの後始末
	LampSound::finalize();
	// LampInputの後始末
	LampInput::finalize();
	// Lampグラフィクスの後始末
	LampGraphics::finalize();
	// デバッグヘッドアップディスプレイ後始末
	DebugHUD::finalize();
	// ウィンドウの破棄
	WindowCreator::destroy(windowHandle_);
	// Lampコアの後始末
	LampCore::finalize();
}
//------------------------------------------------------------------------------
// メインループ
//------------------------------------------------------------------------------
// メインループ
int PrismaticUmbrella::mainLoop(){
	// アプリケーションがアクティブでない時も動作させる
	// アクティブでない時に動作させないようにするにはGetMessage()を使用する
	MSG message;
	bool gotMessage;
	message.message = WM_NULL;
	::PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE);

	// 初期化時間が長かった場合を考え、ループに入る前に入力バッファを一旦クリアする
	LampInput::bufferClear();

	// メッセージループ
	while(message.message != WM_QUIT){
		// メッセージ処理
		gotMessage = (PeekMessage(&message, NULL, 0, 0, PM_REMOVE) != 0);
		if(gotMessage){
			TranslateMessage(&message);
			DispatchMessage(&message);
		}else{
			// メッセージが無ければゲームを実行する
			gameLoop();
		}
	}
	return 0;
}
//------------------------------------------------------------------------------
// ゲームループ
void PrismaticUmbrella::gameLoop(){
	// 1/60秒ごとに追加される入力バッファの数だけ実行する
	// これにより描画フレームレートに左右されないゲーム速度を実現できる
	// ゲーム速度が1FPS以下になるようであれば永久ループを防ぐため入力を切り捨てる
	int inputCount = 0;
	LampInput::waitForInput();
	while(LampInput::hasMoreInput()){
		LampInput::nextInput();
		// 実行
		gameSystem_->run();
		// ゲームFPS計測
		Performance::setGameFPS(gameFPSMeasurement_->measurement());
		inputCount++;
		// 一秒間以上の遅れがある場合は入力を破棄する
		if(inputCount == 60){
			LampInput::bufferClear();
			break;
		}
	}
	// サウンドのプレゼンテーション
	LampSound::presentation();
	// 描画準備
	gameSystem_->renderSetup();
	// FPSの調整、これにより60FPS以上にならない
	fpsController_->sleep();
	// グラフィックスのプレゼンテーション
	GraphicsDevice::getInstance()->presentation();
	// 描画
	gameSystem_->render();
	// 描画FPS計測
	Performance::setDrawFPS(drawFPSMeasurement_->measurement());
	// デバッグヘッドアップディスプレイ表示
	DebugHUD::draw();
}
//------------------------------------------------------------------------------
// ウィンドウプロシージャ関連
//------------------------------------------------------------------------------
// 登録用ウィンドウプロシージャ
LRESULT CALLBACK PrismaticUmbrella::registrationWindowProcedure(
	HWND windowHandle, u_int message, WPARAM wParam, LPARAM lParam){
	// 初期化前ならデフォルトプロシージャのみを呼ぶ
	if(instance_ == NULL){
		return DefWindowProc(windowHandle, message, wParam, lParam);
	}

	// Lampプロシージャ呼び出し
	LRESULT result;
	result = LampCore::windowProcedure(windowHandle, message, wParam, lParam);
	if(result != 0){ return result; }

	// プロシージャ呼び出し
	return instance_->windowProcedure(windowHandle, message, wParam, lParam);
}
//------------------------------------------------------------------------------
// ウィンドウプロシージャ
LRESULT PrismaticUmbrella::windowProcedure(
	HWND windowHandle, u_int message, WPARAM wParam, LPARAM lParam){

	// 最後にデフォルトウィンドウプロシージャを呼ぶ
	return DefWindowProc(windowHandle, message, wParam, lParam);
}
//------------------------------------------------------------------------------
