//------------------------------------------------------------------------------
// 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
 */

#ifndef ANIMATION_MANAGER_H_
#define ANIMATION_MANAGER_H_

#include <Core/Renamer/Renamer.h>
#include <Core/Container/HashMap.h>
#include <Core/Container/ArrayList.h>

namespace Lamp{

class Animation;
class AnimationData;
class AnimationSet;
class CameraAnimation;
class CameraAnimationData;
class SceneNodeAnimation;
class SceneNodeAnimationData;
class CharacterModelAnimation;
class CharacterModelAnimationData;

//------------------------------------------------------------------------------
/**
 * アニメーションマネージャ
 */
class AnimationManager : public Renamer::Database{
public:
	//--------------------------------------------------------------------------
	/**
	 * コンストラクタ
	 */
	AnimationManager();

	/**
	 * デストラクタ
	 */
	virtual ~AnimationManager();

	//--------------------------------------------------------------------------
	// アニメーションセット
	//--------------------------------------------------------------------------
	/**
	 * アニメーションセットの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return アニメーションセット
	 */
	virtual AnimationSet* createAnimationSet(const String& name);

	//--------------------------------------------------------------------------
	// カメラアニメーション
	//--------------------------------------------------------------------------
	/**
	 * カメラアニメーションの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return カメラアニメーション
	 */
	virtual CameraAnimation* createCamera(const String& name);

	/**
	 * カメラアニメーションデータの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return カメラアニメーションデータ
	 */
	virtual CameraAnimationData* createCameraData(const String& name);

	//--------------------------------------------------------------------------
	// シーンノードアニメーション
	//--------------------------------------------------------------------------
	/**
	 * シーンノードアニメーションの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return シーンノードアニメーション
	 */
	virtual SceneNodeAnimation* createSceneNode(const String& name);

	/**
	 * シーンノードアニメーションデータの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return シーンノードアニメーションデータ
	 */
	virtual SceneNodeAnimationData* createSceneNodeData(const String& name);

	//--------------------------------------------------------------------------
	// モデルアニメーション
	//--------------------------------------------------------------------------
	/**
	 * キャラクタモデルアニメーションの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return キャラクタモデルアニメーション
	 */
	virtual CharacterModelAnimation* createCharacterModel(
		const String& name);

	/**
	 * キャラクタモデルアニメーションデータの作成
	 *
	 * 空文字列を名前に指定するとエラーになります。
	 * @param name 名前
	 * @return キャラクタモデルアニメーションデータ
	 */
	virtual CharacterModelAnimationData* createCharacterModelData(
		const String& name);

	//--------------------------------------------------------------------------
	// 破棄、クリア
	//--------------------------------------------------------------------------
	/**
	 * アニメーションの破棄
	 *
	 * アニメーションセットの場合は含まれるアニメーションも破棄されます。
	 * @param animation 破棄するアニメーション
	 */
	virtual void destroy(Animation* animation);

	/**
	 * アニメーションデータの破棄
	 * @param animationData 破棄するアニメーションデータ
	 * @return リファレンスカウント
	 */
	virtual int destroyData(AnimationData* animationData);

	/**
	 * クリア
	 * @return 削除したオブジェクト数
	 */
	virtual int clear();

	//--------------------------------------------------------------------------
	// アニメーション
	//--------------------------------------------------------------------------
	/**
	 * アニメーション数の取得
	 * @return アニメーション数
	 */
	virtual int getCount(){ return animationArray_.getCount(); }

	/**
	 * アニメーションの取得
	 * @param index アニメーションのインデクス
	 * @return アニメーション
	 */
	virtual Animation* get(int index){ return animationArray_.get(index); }

	/**
	 * アニメーションの検索
	 * @param name 検索するアニメーション名
	 * @return アニメーション
	 */
	virtual Animation* search(String name){ return animationHash_.get(name); }

	//--------------------------------------------------------------------------
	// アニメーションデータ
	//--------------------------------------------------------------------------
	/**
	 * アニメーションデータ数の取得
	 * @return アニメーションデータ数
	 */
	virtual int getDataCount(){ return animationDataArray_.getCount(); }

	/**
	 * アニメーションデータの取得
	 * @param index アニメーションデータのインデクス
	 * @return アニメーションデータ
	 */
	virtual AnimationData* getData(int index){
		return animationDataArray_.get(index);
	}

	/**
	 * アニメーションデータの検索
	 * @param name 検索するアニメーションデータ名
	 * @return アニメーションデータ
	 */
	virtual AnimationData* searchData(String name){
		return animationDataHash_.get(name);
	}

	//--------------------------------------------------------------------------
	// リネーム関係
	//--------------------------------------------------------------------------
	/**
	 * アニメーションリネーマの設定
	 * @param renamer 設定するアニメーションリネーマ
	 */
	virtual void setRenamer(Renamer* renamer);

	/**
	 * アニメーションリネーマの取得
	 * @return アニメーションリネーマ
	 */
	virtual Renamer* getRenamer() const{ return animationRenamer_; }

	/**
	 * アニメーション名が存在するかどうか
	 * @param name 存在するかどうか調べる名前
	 * @return 名前が存在すればtrue
	 */
	virtual bool existName(const String& name){
		return (search(name) != NULL);
	}

	/**
	 * アニメーションのリネーム
	 * @param sourceName 元となる名前
	 * @return 重複していない名前
	 */
	virtual String rename(String sourceName){
		if(sourceName.getSize() == 0){
			ErrorOut("AnimationManager::rename() name.getSize() == 0");
			sourceName = "invalid";
		}
		if(!existName(sourceName)){ return sourceName; }
		return getRenamer()->rename(this, sourceName);
	}

	//--------------------------------------------------------------------------
	/**
	 * アニメーションデータリネーマの設定
	 * @param renamer 設定するアニメーションデータリネーマ
	 */
	virtual void setDataRenamer(Renamer* renamer);

	/**
	 * アニメーションデータリネーマの取得
	 * @return アニメーションデータリネーマ
	 */
	virtual Renamer* getDataRenamer() const{ return animationDataRenamer_; }

	/**
	 * アニメーションデータ名が存在するかどうか
	 * @param name 存在するかどうか調べる名前
	 * @return 名前が存在すればtrue
	 */
	virtual bool existDataName(const String& name){
		return (searchData(name) != NULL);
	}

	/**
	 * アニメーションデータのリネーム
	 * @param sourceName 元となる名前
	 * @return 重複していない名前
	 */
	virtual String renameData(String sourceName){
		if(sourceName.getSize() == 0){
			ErrorOut("AnimationManager::renameData() name.getSize() == 0");
			sourceName = "invalid";
		}
		if(!existDataName(sourceName)){ return sourceName; }
		return getDataRenamer()->rename(this, sourceName);
	}

	//--------------------------------------------------------------------------
private:
	// コピーコンストラクタの隠蔽
	AnimationManager(const AnimationManager& copy);

	// 代入コピーの隠蔽
	void operator =(const AnimationManager& copy);

	// アニメーションハッシュ
	HashMap<String, Animation*> animationHash_;
	// アニメーション配列
	ArrayList<Animation*> animationArray_;
	// アニメーションリネーマ
	Renamer* animationRenamer_;

	// アニメーションデータハッシュ
	HashMap<String, AnimationData*> animationDataHash_;
	// アニメーションデータ配列
	ArrayList<AnimationData*> animationDataArray_;
	// アニメーションデータリネーマ
	Renamer* animationDataRenamer_;

};

//------------------------------------------------------------------------------
} // End of namespace Lamp
#endif // End of ANIMATION_MANAGER_H_
//------------------------------------------------------------------------------

