/*!
* @file Creature.h
* @brief ゲーム中のクリーチャーと付随要素のプロトタイプ
* @date 2013/12/11
* @author Deskull
* 2013 Sikabane Works.
*/

#pragma once

//#include "GameEngine.h"

#include "stdafx.h"
#include "BaseStatusTable.h"
#include "Color.h"
#include "Coordinates.h"
#include "Deeangband.h"
#include "Discipline.h"
#include "Direction.h"
#include "Effect.h"

#include "HaveInventory.h"
#include "HaveGameTime.h"
#include "HaveHp.h"
#include "HaveSize.h"
#include "HaveSymbol.h"
#include "HavePosition.h"
#include "Lore.h"
#include "GameConstants.h"
#include "GameInstance.h"
#include "GameMessage.h"
#include "SavingTable.h"
#include "Species.h"

namespace Deeangband
{
	class GameLogger;
	class GameSurface;
	class GameWorld;

	class Field;
	class Floor;
	class Item;

	/*!
	* @class Creature
	* @brief クリーチャーのクラス
	* @details
	* <H1>概要</H1>
	* Creatureクラスは、ゲーム中の独立行動単位であるクリーチャーを実装する。
	* <H2>ステータス要素</H2>
	* クリーチャーは以下のステータス要素を持っている。
	* <ul>
	* <li>名前 / Name</li>
	* <li>クリーチャー種別 / Species</li>
	* <li>擬態クリーチャー種別 / Appearance Species</li>
	* <li>レベル / Level</li>
	* <li>現在HP・最大HP・本来の最大HP/ Current HP, Max HP, Max Max HP</li>
	* <li>現在MP・最大MP・本来の最大MP/ Current MP, Max MP, Max Max MP</li>
	* <li>現在ソウル値・ソウル最大到達値 / Current Soul, Max Soul</li>
	* <li>現在滋養値・最大滋養値 / Current Feed, Max Feed</li>
	* <li>神性レベル / Divine Level</li>
	* <li>現在腕力・最大腕力・限界腕力 / Current STR, Max STR Max Max STR</li>
	* <li>現在知力・最大知力・限界知力 / Current INT, Max INT Max Max INT</li>
	* <li>現在賢さ・最大賢さ・限界賢さ / Current WIS, Max WIS Max Max WIS</li>
	* <li>現在器用・最大器用・限界器用 / Current DEX, Max DEX Max Max DEX</li>
	* <li>現在耐久・最大耐久・限界耐久 / Current CON, Max CON Max Max CON</li>
	* <li>現在魅力・最大魅力・限界魅力 / Current CHA, Max CHA Max Max CHA</li>
	* <li>装甲セーブ値 / Armor Saving</li>
	* <li>回避セーブ値 / Evasion Saving</li>
	* <li>意志セーブ値 / Volition Saving</li>
	* <li>現在フロア / Current Field</li>
	* <li>現在座標 / Current Pisition</li>
	* <li>所持アイテム一覧 / Current Pisition</li>
	* <li>所持スキル一覧 / Current Pisition</li>
	* </ul>
	*/
	class Creature : public GameInstance, public HaveSymbol, public HaveHp, public HaveGameTime, public HavePosition, public HaveInventory, public HaveSize
	{
	private:

		static SOUL soulLevel[CREATURE_MAX_LEVEL]; //!< 必要ソウルレベルテーブル

		MP currentMp;     //!< 現在のMP
		MP maxMp;         //!< 現在の最大MP
		MP maxMaxMp;      //!< 本来の最大MP
		SOUL currentSoul; //!< 現在のソウル値
		SOUL maxSoul;     //!< ソウル最大到達値

		FEED currentFeed; //!< 現在滋養値
		FEED maxFeed;     //!< 最大滋養値

		TAG firstRace; //!< 種族タグ1
		TAG secondRace; //!< 種族タグ2

		Discipline currentDiscipilne; //!< 現在の修養値
		LEVEL divineLevel;            //!< 神性レベル

		BaseStatusTable currentStatus; //!< 現在のステータス
		BaseStatusTable maxStatus;     //!< 通常のステータス
		BaseStatusTable maxMaxStatus;  //!< 限界のステータス

		SavingTable savings; //!< セービング

		std::map<TAG, SKILL_EXP> skillExpList; //!< スキル経験値リスト

		TAG campTag; //!< 所属陣営タグ

		TAG speciesTag; //!< クリーチャー種別Tag
		TAG appearanceSpeciesTag; //!< 擬態先のクリーチャー種別Tag

		HP hpTable[CREATURE_MAX_LEVEL]; //!< ヒットダイスに基づき生成されたレベル毎の基本HP

		MAP_LENGTH sightRange; //!< 標準視界範囲

		Lore lore; //!< 記憶情報
		std::map<int, std::map<int, bool>> sight; //!<視界情報
		std::vector<bool> sightList; //!<視界情報

		/*!
		 * @brief クリーチャー死亡時の処理を行う
		 * @return なし
		 */
		void Creature::die(void);

		/*!
		 * @brief クリーチャーの現MPを増減させる
		 * @param amount 増減MP量
		 * @return なし
		 */
		void Creature::calcMP(MP amount);

		/*!
		* @brief クリーチャーの現MPを設定する
		* @param amount 設定HP量
		* @return なし
		*/
		void Creature::setMP(MP amount);

		/*!
		* @brief クリーチャーのレベル毎基本HPを再計算する
		* @return なし
		*/
		void Creature::calcHPTable(void);

		friend class boost::serialization::access;

		/*!
		* @brief クラスのシリアライズを設定する
		* @param archive アーカイブ化するクラスのアドレス
		* @param version データバージョン
		* @return XMLSerializeテンプレート
		*/
		template<class Archive> void serialize(Archive &archive, const unsigned int version) 
		{
			if(version >= 0)
			{
				archive & boost::serialization::make_nvp("Name", name);
				archive & boost::serialization::make_nvp("FirstRace", firstRace);
				archive & boost::serialization::make_nvp("SecondRace", secondRace);
				archive & boost::serialization::make_nvp("MHP", maxHp);
				archive & boost::serialization::make_nvp("MHP", maxHp);
				archive & boost::serialization::make_nvp("HPTable", hpTable);
				archive & boost::serialization::make_nvp("CMP", currentMp);
				archive & boost::serialization::make_nvp("MMP", maxMp);
				archive & boost::serialization::make_nvp("MMMP", maxMaxMp);
				archive & boost::serialization::make_nvp("CSoul", currentSoul);
				archive & boost::serialization::make_nvp("MSoul", maxSoul);
				archive & boost::serialization::make_nvp("CStatus", currentStatus);
				archive & boost::serialization::make_nvp("MStatus", maxStatus);
				archive & boost::serialization::make_nvp("MMStatus", maxMaxStatus);
				archive & boost::serialization::make_nvp("Height", height);
				archive & boost::serialization::make_nvp("Weight", weight);
				archive & boost::serialization::make_nvp("CFeed", currentFeed);
				archive & boost::serialization::make_nvp("MFeed", maxFeed);
				archive & boost::serialization::make_nvp("Savings", savings);
				archive & boost::serialization::make_nvp("FieldID", fieldID);
				archive & boost::serialization::make_nvp("Position", position);
				archive & boost::serialization::make_nvp("ItemList", itemList);
				archive & boost::serialization::make_nvp("SpeciesTAG", speciesTag);
				archive & boost::serialization::make_nvp("AppearanceSpeciesTAG", appearanceSpeciesTag);
			}
		}

	public:

		/*! 
		 * @brief Creatureクラスコンストラクタ(GameElementメンバ対応)
		 * @param speciesIt 生成元となるクリーチャー種別イテレータ
		 */
		Creature::Creature(std::map<TAG, boost::shared_ptr<Species>>::iterator speciesIt);

		/*! 
		 * @brief Creatureクラスコンストラクタ(GameElementメンバ対応)
		 * @param speciesIt 生成元となるクリーチャーイテレータ参照
		 * @param fieldIt 生成先フィールドイテレータ参照
		 * @param x 生成先X座標
		 * @param y 生成先Y座標
		 */
		Creature::Creature(std::map<TAG, boost::shared_ptr<Species>>::iterator& speciesIt, std::map<ID, boost::shared_ptr<Field>>::iterator& fieldIt, MAP_LENGTH x, MAP_LENGTH y);

		/*! 
		 * @brief Creatureクラスコンストラクタ
		 */
		Creature::Creature(void);

		/*! 
		 * @brief Creatureクラスデストラクタ
		 */
		Creature::~Creature(void);

		/*! 
		 * @brief クリーチャー種別に基づきクリーチャーを生成する
		 * @param speciesPtr 生成元としたいクリーチャー種別
		 * @return なし
		 * @todo 種族タグがVARIABLEなどであった場合の特別処理の実装
		 */
		void Creature::SetSpeciesData(Species *speciesPtr);

		/*! 
		* @brief ダミーデータによる初期化
		* @return なし
		*/
		void Creature::WipeData(void);

		/*!
		* @brief クリーチャーが生存している状態かを返す
		* @return 生存しているならばtrueを返す
		*/
		bool Creature::IsAlive(void);

		/*!
		 * @brief 受けた属性効果を処理する
		 * @param effectPtr
		 * @param amount
		 */
		bool Creature::TakeEffect(Effect* effectPtr, POWER amount);

		/*! 
		* @brief クリーチャーの現レベルを返す
		* @return クリーチャーの現レベル
		*/
		LEVEL Creature::GetLevel(void);

		/*!
		* @brief クリーチャーの通常最大HPを返す
		* @return クリーチャーの通常最大HP
		*/
		HP Creature::GetNorMaxHP(void);

		/*!
		* @brief クリーチャーの現MPを返す
		* @return クリーチャーの現MP
		*/
		MP Creature::GetCurMP(void);

		/*!
		* @brief クリーチャーの現最大MPを返す
		* @return クリーチャーの現最大MP
		*/
		MP Creature::GetMaxMP(void);

		/*!
		* @brief クリーチャーの通常最大MPを返す
		* @return クリーチャーの通常最大MP
		*/
		MP Creature::GetNorMaxMP(void);

		/*!
		* @brief クリーチャーの現装甲セービング値を返す
		* @return クリーチャーの現装甲セービング値
		*/
		AC Creature::GetArmorSaving(void);

		/*!
		* @brief クリーチャーの現回避セービング値を返す
		* @return クリーチャーの現回避セービング値
		*/
		EV Creature::GetEvasionSaving(void);

		/*!
		* @brief クリーチャーの現意思セービング値を返す
		* @return クリーチャーの現意思セービング値
		*/
		VO Creature::GetVolitionSaving(void);

		/*!
		* @brief クリーチャーの所持品リストを返す
		* @return クリーチャー所持品リストマップ
		*/
		std::vector<Item> *Creature::getItemList(void);

		/*!
		* @brief クリーチャーの現ソウル値を返す
		* @return クリーチャーの現ソウル値
		*/
		SOUL Creature::GetCurrentSoul(void);

		/*!
		* @brief クリーチャーのソウル最大到達値を返す
		* @return クリーチャーのソウル最大到達値
		*/
		SOUL Creature::GetMaxSoul(void);

		/*!
		* @brief クリーチャーの現基礎能力値を返す
		* @param stat 取得したい基礎能力値ID
		* @return 基礎能力値の現在値
		*/
		BASE_STATUS Creature::GetCurrentStatus(CREATURE_STATUS stat);

		/*!
		* @brief クリーチャーの平常基礎能力値を返す
		* @param stat 取得したい平常能力値ID
		* @return 基礎能力値の平常値
		*/
		BASE_STATUS Creature::GetMaxStatus(CREATURE_STATUS stat);

		/*!
		* @brief クリーチャーの限界基礎能力値を返す
		* @param stat 取得したい限界能力値ID
		* @return 基礎能力値の限界値
		*/
		BASE_STATUS Creature::GetMaxMAXStatus(CREATURE_STATUS stat);

		/*!
		* @brief クリーチャーの現在修養値を返す
		* @param typ 取得したい現在修養値のID
		* @return 現在修養値
		*/
		int Creature::GetDiscipilnePoint(DISCIPLINE_TYPE typ);

		/*!
		* @brief クリーチャーの現在修養ランクを返す
		* @param typ 取得したい現在修養ランクのID
		* @return 現在修養ランク
		*/
		int Creature::GetDiscipilneRank(DISCIPLINE_TYPE typ);

		/*!
		* @brief ソウル値の新規加算処理
		* @param plus 新規加算ソウル量
		* @return なし
		*/
		void Creature::GainSoul(SOUL plus);

		/*!
		* @brief ソウル値の喪失処理
		* @param amount 喪失ソウル量
		* @return なし
		*/
		void Creature::LostSoul(SOUL amount);

		/*!
		* @brief クリーチャーの神性レベルを返す
		* @return 神性レベル
		*/
		LEVEL Creature::GetDivineLevel(void);

		/*!
		* @brief 現在滋養値を返す
		* @return 現在滋養値
		*/
		FEED Creature::GetCurrentFeedPoint(void);

		/*!
		* @brief 最大滋養値を返す
		* @return 最大滋養値
		*/
		FEED Creature::GetMaxFeedPoint(void);

		/*!
		* @brief クリーチャーのターン時更新定期処理を行う
		* @return なし
		*/
		PLAY_EXIT_CODE Creature::TurnProcess(void);

		/*!
		* @brief クリーチャーのゲーム時間更新定期処理を行う
		* @return なし
		*/
		PLAY_EXIT_CODE Creature::TimeProcess(void);

		/*!
		* @brief クリーチャーの経過総ターン数を返す
		* @return 総ターン数
		*/
		TURN Creature::GetTurn(void);

		/*! 
		* @brief クリーチャー種別のスキル基本経験値を返す
		* @param tag 取得したいスキルのタグ
		* @return 該当スキルの基本経験値、全くの未経験ならば0を返す
		*/
		SKILL_EXP Creature::GetSkillExp(TAG tag);

		/*!
		* @brief クリーチャーの所属陣営Tagを返す
		* @return 所属陣営Tag
		*/
		TAG Creature::GetCampTag(void);

		/*!
		* @brief XMLシリアライズによるゲームデータ保存処理
		* @return なし
		*/
		void Creature::XMLSave(std::string filename);

		/*!
		* @brief クリーチャーが目標クリーチャーに対し白兵戦を行う
		* @param creaturePtr 目標クリーチャーの参照ポインタ
		* @return 白兵処理が実際に処理されたらtrueを返す
		* @todo Creature::Melee()時に発生する影響の実装
		*/
		bool Creature::Melee(Creature *targetPtr);

		/*!
		* @brief クリーチャーがアイテムを取得する処理
		* @param itemIt 追加するアイテムの参照イテレータ
		* @return 実際にアイテムを拾うことができたらtrueを返す
		* @todo Creature::PickUpItem()時に発生する影響の実装
		*/
		bool Creature::PickUpItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを落とす処理
		* @param itemIt 落とすアイテムの参照イテレータ
		* @return 実際にアイテムを落とすことができたらtrueを返す
		* @todo Creature::DropItem()時に発生する影響の実装
		*/
		bool Creature::DropItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを食べる処理
		* @param itemIt 食べるアイテムの参照イテレータ
		* @return 実際にアイテムを食べる処理を試みたらtrueを返す
		* @todo Creature::EatItem()時に発生する影響の実装
		*/
		bool Creature::EatItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを飲む処理
		* @param itemIt 飲むアイテムの参照イテレータ
		* @return 実際にアイテムを飲む処理を試みたらtrueを返す
		* @todo Creature::QuaffItem()時に発生する影響の実装
		*/
		bool Creature::QuaffItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを発動する処理
		* @param itemIt 発動するアイテムの参照イテレータ
		* @return 実際にアイテムを発動処理を試みたらtrueを返す
		* @todo Creature::ActivateItem()時に発生する影響の実装
		*/
		bool Creature::ActivateItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを投擲する処理
		* @param itemIt 投擲するアイテムの参照イテレータ
		* @return 実際にアイテム投擲処理を試みたらtrueを返す
		* @todo Creature::ThrowItem()時に発生する影響の実装
		*/
		bool Creature::ThrowItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		* @brief クリーチャーがアイテムを読む処理
		* @param itemIt 読むアイテムの参照イテレータ
		* @return 実際にアイテムを読む処理を試みたらtrueを返す
		* @todo Creature::ReadItem()時に発生する影響の実装
		*/
		bool Creature::ReadItem(std::map<ID, boost::shared_ptr<Item>>::iterator itemIt);

		/*!
		 * @brief クリーチャーが指定地点に侵入可能かを返す
		 * @param floor 床情報の参照ポインタ
		 * @return 侵入可能ならばtrueを返す
		 * @todo 完全な実装を行う
		 */
		bool Creature::CanEnterPosition(Floor *floor);

		/*!
		 * @brief クリーチャーの記憶情報を返す。
		 * @return 記憶情報の参照ポインタ
		 */
		Lore* Creature::GetLore() {return &this->lore; }

		/*!
		 * @brief クリーチャーのフィールド認知情報を更新する
		 * @return なし
		 */
		void Creature::UpdateFieldLore(void);

		/*!
		 * @brief 指定地点がクリーチャーの視界に入っているかを返す。
		 * @return 視界に入っているなら true
		 */
		bool Creature::InSight(MAP_LENGTH x, MAP_LENGTH y);

		/*!
		 * @brief クリーチャーが指定の方向に歩行する
		 * @param creaturePtr クリーチャーの参照ポインタ
		 * @param direction 歩行する方向
		 * @return 移動が実際に行われたらtrue
		 */
		ACTION_RESULT Creature::Walk(DIRECTION direction);

		/*!
		 * @brief クリーチャーが指定の方向にあるものを開ける
		 * @param creaturePtr クリーチャーの参照ポインタ
		 * @param direction 開けるものの方向
		 * @return 
		 */
		ACTION_RESULT Creature::Open(DIRECTION direction);

		/*!
		 * @brief クリーチャーが指定の方向にあるものを閉じる
		 * @param creaturePtr クリーチャーの参照ポインタ
		 * @param direction 閉じるものの方向
		 * @return 
		 */
		ACTION_RESULT Creature::Close(DIRECTION direction);

		/*!
		 * @brief クリーチャーが指定の方向にあるものを解除
		 * @param creaturePtr クリーチャーの参照ポインタ
		 * @param direction 解除先の方向
		 * @return
		 */
		ACTION_RESULT Creature::Disarm(DIRECTION direction);

		/*!
		 * @brief 受け取ったゲームコマンドを処理する
		 * @param command 実行するゲームコマンド
		 * @return ゲーム終了コード
		 */
		PLAY_EXIT_CODE Creature::DoGameCommand(GAME_COMMAND command);

	};

}

BOOST_CLASS_VERSION(Deeangband::Creature, 10);
