//------------------------------------------------------------------------------
// 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 "stdafx.h"
#include "SceneOptimizer.h"
#include "Core/Utility/StringTokenizer.h"
#include "Core/InputOutput/FilePath.h"
#include "Graphics/System/LampGraphics.h"
#include "Graphics/InputOutput/TextSceneLoader.h"
#include "Graphics/InputOutput/BinarySceneLoader.h"
#include "Graphics/InputOutput/TextSceneSaver.h"
#include "Graphics/InputOutput/BinarySceneSaver.h"
#include "Animation/System/AnimationManager.h"
#include "Animation/System/Animation.h"
#include "Animation/InputOutput/TextAnimationLoader.h"
#include "Animation/InputOutput/TextAnimationSaver.h"
#include "Core/InputOutput/TextFileReader.h"
#include "Graphics/SceneFilter/SceneFilter.h"

//------------------------------------------------------------------------------
// エントリポイント
int _tmain(int argc, _TCHAR* argv[]){
	if(argc == 1){
		printf("使用方法\n"
			"　-scene [filename] シーンファイルを指定します。\n"
			"　-animation [filename] アニメーションファイルを指定します。\n"
			"　-command [filename] コマンドファイルを指定します。\n");
		return 0;
	}
	SceneOptimizer optimizer;
	return optimizer.run();
}
//------------------------------------------------------------------------------
// コンストラクタ
SceneOptimizer::SceneOptimizer() :
	scene_(NULL), animationManager_(NULL), reader_(NULL){
}
//------------------------------------------------------------------------------
// デストラクタ
SceneOptimizer::~SceneOptimizer(){
	SafeDelete(reader_);
	if(animationManager_ != NULL){
		animationManager_->clear();
		delete animationManager_;
		animationManager_ = NULL;
	}
	if(scene_ != NULL){
		scene_->clear();
		LampGraphics::destroyScene(scene_);
		scene_ = NULL;
	}
}
//------------------------------------------------------------------------------
// 実行
int SceneOptimizer::run(){
	// コマンドライン解析
	if(!readCommandLine()){ return 1; }
	// エラーチェック
	if(!errorCheck()){ return 1; }
	// シーンのロード
	if(!loadScene()){ return 1; }
	// アニメーションのロード
	if(!loadAnimation()){ return 1; }
	// コマンドのロード
	reader_ = new TextFileReader(commandName_);
	// フィルタ
	SceneFilter sceneFilter(scene_);
	while(!reader_->isEnd()){
		String command = reader_->readLine();
		if(command.getSize() == 0){ continue; }
		if(!sceneFilter.filter(command)){
			ErrorOut("フィルタに失敗しました\n%s\n", command.getBytes());
			return 1;
		}
	}
	// シーンのセーブ
	if(!saveScene()){ return 1; }
	// アニメーションのセーブ
	if(!saveAnimation()){ return 1; }
	return 0;
}
//------------------------------------------------------------------------------
// コマンドラインの読み込み
bool SceneOptimizer::readCommandLine(){
	String command(GetCommandLine());
	StringTokenizer tokenizer(command);
	while(tokenizer.hasMoreTokens()){
		String token = tokenizer.getNextToken();
		if(token == "-scene"){
			// シーン名の読み込み
			if(!tokenizer.hasMoreTokens()){
				ErrorOut("-sceneオプションが設定されていますが、"
					"シーン名がありません\n");
				return false;
			}
			sceneName_ = tokenizer.getNextToken();
		}else if(token == "-animation"){
			// アニメーション名の読み込み
			if(!tokenizer.hasMoreTokens()){
				ErrorOut("-animationオプションが設定されていますが、"
					"アニメーション名がありません\n");
				return false;
			}
			animationName_ = tokenizer.getNextToken();
		}else if(token == "-command"){
			// コマンド名の読み込み
			if(!tokenizer.hasMoreTokens()){
				ErrorOut("-commandオプションが設定されていますが、"
					"コマンド名がありません\n");
				return false;
			}
			commandName_ = tokenizer.getNextToken();
		}
	}
	return true;
}
//------------------------------------------------------------------------------
// エラーチェック
bool SceneOptimizer::errorCheck(){
	if((sceneName_.getSize() == 0) && (animationName_.getSize() == 0)){
		ErrorOut("シーン名、アニメーション名共に指定されていません\n");
		return false;
	}
	if(sceneName_.getSize() != 0){
		FilePath sceneFilePath(sceneName_);
		if(!sceneFilePath.existFile()){
			ErrorOut("シーンファイルが存在しません\n%s\n",
				sceneName_.getBytes());
			return false;
		}
	}
	if(animationName_.getSize() != 0){
		FilePath animationFilePath(animationName_);
		if(!animationFilePath.existFile()){
			ErrorOut("アニメーションファイルが存在しません\n%s\n",
				animationName_.getBytes());
			return false;
		}
	}
	if(commandName_.getSize() == 0){
		ErrorOut("コマンド名が指定されていません\n");
		return false;
	}
	FilePath commandFilePath(commandName_);
	if(!commandFilePath.existFile()){
		ErrorOut("コマンドファイルが存在しません\n%s\n",
			commandName_.getBytes());
		return false;
	}
	return true;
}
//------------------------------------------------------------------------------
// シーンのロード
bool SceneOptimizer::loadScene(){
	if(sceneName_.getSize() == 0){ return true; }
	FilePath sceneFilePath(sceneName_);
	if(sceneFilePath.getExtension() == "tsn"){
		scene_ = LampGraphics::createScene(sceneFilePath.getName());
		TextSceneLoader* loader = new TextSceneLoader();
		loader->load(sceneFilePath.getPath(), scene_);
		delete loader;
	}else if(sceneFilePath.getExtension() == "bsn"){
		scene_ = LampGraphics::createScene(sceneFilePath.getName());
		BinarySceneLoader* loader = new BinarySceneLoader();
		loader->load(sceneFilePath.getPath(), scene_);
		delete loader;
	}else{
		ErrorOut("拡張子が正しくありません\n%s\n",
			sceneName_.getBytes());
		return false;
	}
	return true;
}
//------------------------------------------------------------------------------
// シーンのセーブ
bool SceneOptimizer::saveScene(){
	if(scene_ == NULL){ return true; }
	FilePath sceneFilePath(sceneName_);
	if(sceneFilePath.getExtension() == "tsn"){
		TextSceneSaver* textSceneSaver = new TextSceneSaver();
		textSceneSaver->save(sceneFilePath.getPath(), scene_);
		delete textSceneSaver;
	}else if(sceneFilePath.getExtension() == "bsn"){
		BinarySceneSaver* binarySceneSaver = new BinarySceneSaver();
		binarySceneSaver->save(sceneFilePath.getPath(), scene_);
		delete binarySceneSaver;
	}else{
		ErrorOut("拡張子が正しくありません\n%s\n",
			sceneName_.getBytes());
		return false;
	}
	return true;
}
//------------------------------------------------------------------------------
// アニメーションのロード
bool SceneOptimizer::loadAnimation(){
	if(animationName_.getSize() == 0){ return true; }
	FilePath animationFilePath(animationName_);
	if(animationFilePath.getExtension() == "tam"){
		animationManager_ = new AnimationManager();
		TextAnimationLoader* loader = new TextAnimationLoader();
		loader->load(animationFilePath.getPath(), animationManager_);
		delete loader;
	}else{
		ErrorOut("拡張子が正しくありません\n%s\n",
			animationName_.getBytes());
		return false;
	}
	// シーンがあればバインドする
	if(scene_ != NULL){
		Animation* animation =
			animationManager_->search(animationFilePath.getName());
		if(animation == NULL){
			ErrorOut("ルートアニメーションが見つかりません\n%s\n",
				animationFilePath.getName().getBytes());
			return false;
		}
		if(!animation->bind(scene_)){
			ErrorOut("アニメーションのバインドに失敗しました\n");
			return false;
		}
	}
	return true;
}
//------------------------------------------------------------------------------
// アニメーションのセーブ
bool SceneOptimizer::saveAnimation(){
	if(animationManager_ == NULL){ return true; }
	FilePath animationFilePath(animationName_);
	if(animationFilePath.getExtension() == "tam"){
		TextAnimationSaver* textAnimationSaver = new TextAnimationSaver();
		textAnimationSaver->save(
			animationFilePath.getPath(), animationManager_);
		delete textAnimationSaver;
	}else{
		ErrorOut("拡張子が正しくありません\n%s\n",
			animationName_.getBytes());
		return false;
	}
	return true;
}
//------------------------------------------------------------------------------
