//------------------------------------------------------------------------------
// 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 "LampBasic.h"
#include "Animation/System/AnimationManager.h"
#include "Core/Renamer/CountRenamer.h"
#include "Animation/System/AnimationSet.h"
#include "Animation/Camera/CameraAnimation.h"
#include "Animation/SceneNode/SceneNodeAnimation.h"
#include "Animation/Model/CharacterModelAnimation.h"

namespace Lamp{

//------------------------------------------------------------------------------
// コンストラクタ
AnimationManager::AnimationManager() :
	animationHash_(256, 0.75f), animationArray_(256),
	animationDataHash_(256, 0.75f), animationDataArray_(256){
	animationRenamer_ = new CountRenamer();
	animationDataRenamer_ = new CountRenamer();
}
//------------------------------------------------------------------------------
// デストラクタ
AnimationManager::~AnimationManager(){
	Assert(animationHash_.getCount() == 0);
	Assert(animationArray_.getCount() == 0);
	Assert(animationDataHash_.getCount() == 0);
	Assert(animationDataArray_.getCount() == 0);
	if(getCount() != 0){ clear(); }
	if(getDataCount() != 0){ clear(); }
	SafeDelete(animationDataRenamer_);
	SafeDelete(animationRenamer_);
}
//------------------------------------------------------------------------------
// アニメーションセット
//------------------------------------------------------------------------------
// アニメーションセットの作成
AnimationSet* AnimationManager::createAnimationSet(const String& name){
	AnimationSet* animation = new AnimationSet(rename(name), this);
	animationHash_.put(animation->getName(), animation);
	animationArray_.add(animation);
	return animation;
}
//------------------------------------------------------------------------------
// カメラアニメーション
//------------------------------------------------------------------------------
// カメラアニメーションの作成
CameraAnimation* AnimationManager::createCamera(
	const String& name){
	CameraAnimation* animation = new CameraAnimation(rename(name), this);
	animationHash_.put(animation->getName(), animation);
	animationArray_.add(animation);
	return animation;
}
//------------------------------------------------------------------------------
// カメラアニメーションデータの作成
CameraAnimationData* AnimationManager::createCameraData(
	const String& name){
	CameraAnimationData* animationData =
		new CameraAnimationData(renameData(name), this);
	animationDataHash_.put(animationData->getName(), animationData);
	animationDataArray_.add(animationData);
	return animationData;
}
//------------------------------------------------------------------------------
// シーンノードアニメーション
//------------------------------------------------------------------------------
// シーンノードアニメーションの作成
SceneNodeAnimation* AnimationManager::createSceneNode(
	const String& name){
	SceneNodeAnimation* animation = new SceneNodeAnimation(rename(name), this);
	animationHash_.put(animation->getName(), animation);
	animationArray_.add(animation);
	return animation;
}
//------------------------------------------------------------------------------
// シーンノードアニメーションデータの作成
SceneNodeAnimationData* AnimationManager::createSceneNodeData(
	const String& name){
	SceneNodeAnimationData* animationData =
		new SceneNodeAnimationData(renameData(name), this);
	animationDataHash_.put(animationData->getName(), animationData);
	animationDataArray_.add(animationData);
	return animationData;
}
//------------------------------------------------------------------------------
// モデルアニメーション
//------------------------------------------------------------------------------
// キャラクタモデルアニメーションの作成
CharacterModelAnimation* AnimationManager::createCharacterModel(
	const String& name){
	CharacterModelAnimation* animation =
		new CharacterModelAnimation(rename(name), this);
	animationHash_.put(animation->getName(), animation);
	animationArray_.add(animation);
	return animation;
}
//------------------------------------------------------------------------------
// キャラクタモデルアニメーションデータの作成
CharacterModelAnimationData* AnimationManager::createCharacterModelData(
	const String& name){
	CharacterModelAnimationData* animationData =
		new CharacterModelAnimationData(renameData(name), this);
	animationDataHash_.put(animationData->getName(), animationData);
	animationDataArray_.add(animationData);
	return animationData;
}
//------------------------------------------------------------------------------
// 破棄、クリア
//------------------------------------------------------------------------------
// アニメーションの破棄
void AnimationManager::destroy(Animation* animation){
	// アニメーションセットの場合は下位のアニメーションも削除する
/*
	if(animation->isAnimationSet()){
		AnimationSet* animationSet = animation->castAnimationSet();
		int animationCount = animationSet->getAnimationCount();
		for(int i = animationCount - 1; i >= 0; i--){
			Animation* child = animationSet->getAnimation(i);
			animationSet->removeAnimation(child);
			destroy(child);
		}
	}
*/
	// データベースから検索して削除
	if(animationArray_.removeByValue(animation) == -1){
		ErrorOut("AnimationManager::destroy() "
			"Not found object in array");
	}
	if(animationHash_.remove(animation->getName()) == NULL){
		ErrorOut("AnimationManager::destroy() "
			"Not found object in hashmap");
	}
	delete animation;
}
//------------------------------------------------------------------------------
// アニメーションデータの破棄
int AnimationManager::destroyData(AnimationData* animationData){
	// 参照が残っていれば削除しない
	int referenceCount = animationData->getReferenceCount();
	Assert(referenceCount >= 0);
	if(referenceCount != 0){ return referenceCount; }
	// データベースから検索して削除
	if(animationDataArray_.removeByValue(animationData) == -1){
		ErrorOut("AnimationManager::destroyData() "
			"Not found object in array");
	}
	if(animationDataHash_.remove(animationData->getName()) == NULL){
		ErrorOut("AnimationManager::destroyData() "
			"Not found object in hashmap");
	}
	delete animationData;
	return 0;
}
//------------------------------------------------------------------------------
// クリア
int AnimationManager::clear(){
	int result = 0;
	// アニメーションの削除
	int count = getCount();
	for(int i = 0; i < count; i++){ delete get(i); }
	result += count;
	// アニメーションデータの削除
	int dataCount = getDataCount();
	for(int i = 0; i < dataCount; i++){ delete getData(i); }
	result += dataCount;
	// コンテナの削除
	animationArray_.clear();
	animationHash_.clear();
	animationDataArray_.clear();
	animationDataHash_.clear();
	return result;
}
//------------------------------------------------------------------------------
// リネーマ
//------------------------------------------------------------------------------
// アニメーションリネーマの設定
void AnimationManager::setRenamer(Renamer* renamer){
	Assert(renamer != NULL);
	SafeDelete(animationRenamer_);
	animationRenamer_ = renamer;
}
//------------------------------------------------------------------------------
// アニメーションデータリネーマの設定
void AnimationManager::setDataRenamer(Renamer* renamer){
	Assert(renamer != NULL);
	SafeDelete(animationDataRenamer_);
	animationDataRenamer_ = renamer;
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
