//------------------------------------------------------------------------------
// 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
 * Xファイルコンバータ実装
 * @author Junpee
 */

#include <LampBasic.h>
#include <System/XFileConverter.h>
#include <Core/InputOutput/FilePath.h>
#include <Input/Joystick/Joystick.h>
#include <Framework/Utility/PS2PadCameraController.h>
#include <Graphics/System/LampGraphics.h>
#include <Graphics/Renderer/Renderer.h>
#include <Graphics/Camera/CameraManager.h>
#include <Graphics/SceneNode/SceneNode.h>
#include <Graphics/MeshData/MeshDataManager.h>
#include <Graphics/Light/LightManager.h>
#include <Graphics/SceneFilter/SceneFilter.h>
#include <Graphics/InputOutput/TextSceneSaver.h>
#include "XTranslator/XMeshTranslator.h"

//------------------------------------------------------------------------------
// プログラムエントリポイント
//------------------------------------------------------------------------------
// メイン関数
int WINAPI WinMain(
	HINSTANCE instance, HINSTANCE previousInstance, LPSTR command, int show){
	String commandString(command);
	XFileConverter converter(commandString);
	return converter.execute(instance);
}
//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
XFileConverter::XFileConverter(const String& command) :
	BasicFramework("XFileConverter"), command_(command), renderer_(NULL),
	scene_(NULL), camera_(NULL), pointLight_(NULL), cameraController_(NULL){
}
//------------------------------------------------------------------------------
// デストラクタ
XFileConverter::~XFileConverter(){
}
//------------------------------------------------------------------------------
// フレームワークメソッド
//------------------------------------------------------------------------------
// 初期化
bool XFileConverter::initialize(){
	// 引数の解析
	if(command_.isEmpty()){
		ErrorOut("XFileConverter::initialize() 引数がありません");
		return false;
	}
	// Xファイル名
	String xFileName = command_;
	FilePath xFilePath(xFileName);

	// レンダラ初期化
	renderer_ = new Renderer();
	// カメラコントローラ初期化
	cameraController_ = new PS2PadCameraController();
	cameraController_->searchJoystick();
	// シーンの作成
	scene_ = LampGraphics::createScene(xFilePath.getName());

	// Xファイルのコンバート
	XMeshTranslator xMeshTranslator_;
	if(!xMeshTranslator_.translateXFile(xFilePath, scene_)){
		ErrorOut("XFileConverter::initialize() Xファイルのロードに失敗しました");
		return false;
	}

	// シーンフィルタ
	SceneFilter sceneFilter(scene_);
	// ピクチャパスの変更
	if(!sceneFilter.filter("ChangePicturePath pictures/")){
		ErrorOut("XFileConverter::initialize() "
			"ピクチャパスの変更に失敗しました");
		return false;
	}
	// バウンディングボックス算出
	if(!sceneFilter.filter("CalculateBoundingBox")){
		ErrorOut("XFileConverter::initialize() "
			"バウンディングボックスの算出に失敗しました");
		return false;
	}
	// バウンディングスフィア算出
	if(!sceneFilter.filter("CalculateBoundingSphere")){
		ErrorOut("XFileConverter::initialize() "
			"バウンディングスフィアの算出に失敗しました");
		return false;
	}
	// シーンの論理チェック
	if(!sceneFilter.filter("SceneLogicCheck")){
		ErrorOut("XFileConverter::initialize() "
			"シーンの論理チェックに失敗しました");
		return false;
	}

	// シーンの出力、入力パスと同じ所に出力する
	String fileName = xFilePath.getFolderPath() + xFilePath.getName() + ".tsn";
	TextSceneSaver* textSceneSaver = new TextSceneSaver();
	textSceneSaver->save(fileName, scene_);
	delete textSceneSaver;

	// カメラの作成
	camera_ = scene_->getCameraManager()->createCamera("camera");
	scene_->setCurrentCamera(camera_);
	cameraController_->setCamera(camera_);
	// カメラ距離の算出
	float distance = 2.f;
	MeshDataManager* meshDataManager = scene_->getMeshDataManager();
	int meshDataCount = meshDataManager->getCount();
	for(int i = 0; i < meshDataCount; i++){
		MeshData* meshData = meshDataManager->get(i);
		float radius = meshData->getBoundingSphere().getRadius();
		if(radius > distance){ distance = radius; }
	}
	camera_->setTransformation(
		Vector3::zero, Vector3(0.f, distance * 0.5f, distance * 1.5f));

	// ライトの作成
	LightManager* lightManager = scene_->getLightManager();
	Color3f lightColor(1.f, 1.f, 1.f);
	directionalLight_ =
		lightManager->createDirectionalLight("directionalLight");
	directionalLight_->setDirection(Vector3(-1.f, -1.f, -1.f));
	directionalLight_->setColor(lightColor);
	scene_->getRootNode()->addSceneLeaf(directionalLight_);
	pointLight_ = lightManager->createPointLight("pointLight");
	pointLight_->setColor(lightColor);
	pointLight_->setEnabled(false);
	scene_->getRootNode()->addSceneLeaf(pointLight_);
	return true;
}
//------------------------------------------------------------------------------
// 後始末
void XFileConverter::finalize(){
	// カメラコントローラの破棄
	SafeDelete(cameraController_);
	// シーンの破棄
	scene_->clear();
	LampGraphics::destroyScene(scene_);
	// レンダラの破棄
	SafeDelete(renderer_);
}
//------------------------------------------------------------------------------
// 実行
void XFileConverter::run(){
	// カメラ操作
	cameraController_->control();
	Joystick* cameraPad = cameraController_->getJoystick();
	if(cameraPad != NULL){
		if(cameraPad->buttonDown(0)){
			bool enabled = directionalLight_->isEnabled();
			directionalLight_->setEnabled(!enabled);
			pointLight_->setEnabled(enabled);
		}
	}
	pointLight_->setPosition(camera_->getPosition());
}
//------------------------------------------------------------------------------
// レンダリング準備
void XFileConverter::renderSetup(){
	// トラバース、先にカメラの設定を終えている必要がある
	scene_->traverse();
	// レンダリング準備
	renderer_->renderingSetup(scene_);
}
//------------------------------------------------------------------------------
// レンダリング
void XFileConverter::render(){
	// レンダリング
	renderer_->rendering();
}
//------------------------------------------------------------------------------
// 情報描画
void XFileConverter::drawInformation(){
	BasicFramework::drawInformation();
}
//------------------------------------------------------------------------------
