#pragma once

#include <set>
#include <map>

#include "Rune Engine/Rune/Rune.h"						// 3D引擎
#include "Rune Engine/Rune/Rune Engine Audio.h"
#include "Rune Engine/Rune/Rune Engine D3D.h"
#include "Rune Engine/Rune/Script/RuScript_LuaIntegration.h"
#include "Rune Engine/DirectInput/directinput.h"		// 輸入裝置
#include "Rune Engine/texture/textureimage.h"

class IBaseSprite;

#define IsSame(a, b)					(((a) > (b)) ? ((a)-(b) < 0.00001f) : ((b)-(a) < 0.00001f))

enum SpriteObjectType {
	eSpriteObject_Unknown			= 0,
	eSpriteObject_Player,
	eSpriteObject_NPC,
	eSpriteObject_Effect
};

enum SpriteClassType {
	eSpriteClass_Base				= 0,	
	eSpriteClass_Role,
	eSpriteClass_Effect,
	eSpriteClass_Effect_Line
};

enum SpriteMotionType {
	eMotion_Null					= 0,

	// normal
	eMotion_Stand,
	eMotion_Stand_Idle01,
	eMotion_Stand_Idle02,
	eMotion_Stand_Idle03,	

	// move
	eMotion_Run_Forward,
	eMotion_Run_Back,	
	eMotion_Walk_Forward,
	eMotion_Walk_Back,
	eMotion_Shuffle_Left,				// 轉左
	eMotion_Shuffle_Right,				// 轉右

	// 游泳
	eMotion_Swim_Idle,					// 游泳-閒置水面(loop)
	eMotion_Swim_Forward,				// 游泳-向前
	eMotion_Swim_Back,					// 游泳-向後
	eMotion_Swim_Left,					// 游泳-左側游
	eMotion_Swim_Right,					// 游泳-右側游
	eMotion_Drown,						// 溺水
	eMotion_Death_Drowned,				// 溺水-死亡
	eMotion_Dead_Water,					// 溺水(死在水中)

	// jump
	eMotion_Jump_Up,
	eMotion_Jump_Loop,
	eMotion_Jump_Down,
	eMotion_Jump_Lendrun,

	// fight
	eMotion_Unarmed_Idle,
	eMotion_Unarmed_Attack01,
	eMotion_Unarmed_Attack02,
	eMotion_Unarmed_Attack03,
	eMotion_Unarmed_Parry,
	eMotion_1H_Idle,
	eMotion_1H_Attack01,
	eMotion_1H_Attack02,
	eMotion_1H_Attack03,
	eMotion_1H_Pierce01,
	eMotion_OH_Pierce01,
	eMotion_OH_Attack01,
	eMotion_1H_Parry,
	eMotion_2H_Idle,
	eMotion_2H_Attack01,
	eMotion_2H_Attack02,
	eMotion_2H_Attack03,
	eMotion_2H_Parry,
	eMotion_Polearm_Idle,
	eMotion_Polearm_Attack01,
	eMotion_Polearm_Attack02,
	eMotion_Polearm_Attack03,
	eMotion_Polearm_Parry,
	eMotion_Bow_Idle,
	eMotion_Bow_Ready,
	eMotion_Bow_Channel,
	eMotion_Bow_Release,
	eMotion_Bow_Parry,
	eMotion_Gun_Idle,
	eMotion_Gun_Ready,
	eMotion_Gun_Channel,
	eMotion_Gun_Release,
	eMotion_Gun_Parry,

	eMotion_Shield_Block,				// 盾類—格檔
	eMotion_Shield_Bash,				// 盾類—盾擊

	// 施法動作
	eMotion_Casting_Delay,				// 類似集氣動作(loop)
	eMotion_Cast_01,					// 出手動作,對自己
	eMotion_Cast_02,					// 出手動作,對目標
	eMotion_Continuous_Cast,			// 出手動作,持續施法(loop)

	eMotion_1H_Holster,					// 左右側拔取武器
	eMotion_1H_Unholster,				// 左右側收取武器
	eMotion_2H_Holster,					// 後側拔取武器
	eMotion_2H_Unholster,				// 後側收取武器

	eMotion_Dodge,						// 閃躲
	eMotion_Hurt,						// 受傷
	eMotion_Death,						// 死亡(倒下動作)
	eMotion_Dead,						// 死亡(趴在地板)(loop)
	eMotion_Revive,						// 復活
	eMotion_Dazed,						// 暈眩
	eMotion_Slumber,					// 睡眠
	eMotion_Knockdown_Start,			// 重擊後退-開始
	eMotion_Knockdown_Idle,				// 重擊後退(loop)
	eMotion_Knockdown_End,				// 重擊後退-結束
	eMotion_Knockdown_Recover,			// 重擊後退-起身

	// 生活技能
	eMotion_Fishing_Cast,				// 釣魚-甩竿
	eMotion_Fishing_Idle,				// 釣魚-持續(loop)
	eMotion_Fishing_Reel,				// 釣魚-收竿
	eMotion_Gathering_Start,			// 採集-開始
	eMotion_Gathering_Idle,				// 採集(loop)
	eMotion_Gathering_End,				// 採集-結束
	eMotion_Mining_Start,				// 挖礦-開始
	eMotion_Mining_Idle,				// 挖礦(loop)
	eMotion_Mining_End,					// 挖礦-結束
	eMotion_Crafting_Start,				// 加工-開始
	eMotion_Crafting_Idle,				// 加工(loop)
	eMotion_Crafting_End,				// 加工-結束

	// emotion
	eMotion_Sit,						// 坐下
	eMotion_Sit_Idle,					// 坐(loop)
	eMotion_Stand_Up,					// 起立(由坐下站起)
	eMotion_Sleep_Down,					// 睡(倒下)
	eMotion_Sleep_Idle,					// 睡(loop)
	eMotion_Sleep_Up,					// 睡(起立)
	eMotion_Crouch_Down,				// 蹲下
	eMotion_Crouch_Idle,				// 蹲(loop)
	eMotion_Crouch_Up,					// 蹲起
	eMotion_Drink,						// 喝
	eMotion_Eat,						// 吃
	eMotion_Use_Item,					// 使用物品

	eMotion_Speak01,					// 說話1
	eMotion_Speak02,					// 說話2
	eMotion_Head_Nod,					// 點頭（是、好）
	eMotion_Head_Shake,					// 搖頭（否、不要）
	eMotion_Laugh,						// 笑
	eMotion_Angry,						// 生氣
	eMotion_Cry,						// 哭泣
	eMotion_Approval,					// 贊同
	eMotion_Victory,					// 歡呼(勝利)
	eMotion_Applause,					// 拍手
	eMotion_Salute,						// 敬禮
	eMotion_Wave,						// 招手
	eMotion_Point,						// 手指前方
	eMotion_Provoke,					// 挑撥
	eMotion_Beg,						// 乞討
	eMotion_Dance,						// 跳舞
	eMotion_Surrender,					// 認輸（甘拜下風）
	eMotion_Signature,					// 招牌動作（超人戰隊）
	eMotion_Threaten,					// 威嚇

	// effect
	eMotion_Effect_Appear,
	eMotion_Effect_Idle,
	eMotion_Effect_Disappear,
	eMotion_Effect_Explode
};

enum SpriteAttachPoint {
	eAttach_Null					= 0,	
	eAttach_Top,
	eAttach_Down,
	eAttach_Hit_Point1,
	eAttach_Hit_Point2,
	eAttach_Back_Polearm,
	eAttach_Back_Shield,
	eAttach_Back_Sword,
	eAttach_Back_Gun,
	eAttach_Back_Bow,
	eAttach_Name_Title,
	eAttach_Hand_Shield,
	eAttach_Left_Hand,
	eAttach_Right_Hand,
	eAttach_Left_Foot,
	eAttach_Right_Foot,
	eAttach_Left_Weapon,
	eAttach_Right_Weapon,
	eAttach_Shoot,
	eAttach_Ride_01,
	eAttach_Ride_02,
	eAttach_Freeze_Down,
	eAttach_Freeze_Hit,
};

enum SpriteMoveDirection {
	eMove_NULL						= 0,
	eMove_Forward,
	eMove_Forward_Left,
	eMove_Forward_Right,
	eMove_Side_Left,
	eMove_Side_Right,
	eMove_Back,
	eMove_Back_Left,
	eMove_Back_Right
};

//-----------------------------------------------------------------------------
// 觸發事件
typedef bool (*SpriteCallBack)		( float elapsedTime, IBaseSprite* sprite, void* date );

//-----------------------------------------------------------------------------
struct SpriteEventInfo
{
	float nowTime;
	SpriteCallBack func;
	int userData[6];
};

using namespace std;

//-----------------------------------------------------------------------------
// Model 動作事件處理
class CRuGlobalEventManager : public IRuEntityEventListener
{
protected:
	CRuEntity_Container_Impl*		m_controllerFrame;				//!< Frame that contains all controllers

public:
	CRuGlobalEventManager();
	virtual							~CRuGlobalEventManager();

	void							Update(REAL elapsedTime);

	void							AddEntity( CRuEntity* pRuEntity );

	virtual BOOL					HandleEvent(CRuEntity *entity, INT32 eventID, INT32 eventParameter0, INT32 eventParameter1, const char *eventString, REAL eventDuration, void *userData);
};

//-----------------------------------------------------------------------------
class IBaseSprite
{
public:
	static	void					Initialize();
	static	void					Shutdown();
	static	void					UpdateAll( float elapsedTime );
	static	void					RenderAll();	
	static	void					SetFontType( CRuFontType* pFontType );
	static	void					SetRuTerrain( CRuOptimalTerrain* pRuTerrain );
	static	void					SetMainPlayerId( int id );
	static	bool					CheckedSpriteIsLife( IBaseSprite* pBaseSprite );
	static	const char*				GetAttachPointName( int point );
	static	int						GetAttachPointEnum( const char* point );
	static	const char*				GetMotionName( int motion );
	static	int						GetMotionEnum( const char* motion );
	static	void					SetRuEntityDirection( CRuEntity* pRuEntity, CRuVector3& dir );
	static	bool					TerrainTest( CRuVector3& dir, CRuVector3& pos, CRuVector3 *newPos );
	static	bool					TerrainTestHight( bool isDown, CRuVector3& pos, float& y );	
	static	bool					ModifyPosOnTerrain( CRuVector3& pos );

protected:
	static	void					Insert( IBaseSprite* pSprite );
	static	void					Erase( IBaseSprite* pSprite );

public:
	IBaseSprite();
	virtual ~IBaseSprite();

	virtual	void					Update( float elapsedTime );
	virtual void					Render();
	virtual	void					ReceiveDestruct( IBaseSprite* pSprite )	= 0;
	
	virtual	void					SetIdentify( int id )					{ m_id = id; }
	virtual	int						GetIdentify()							{ return m_id; }
	virtual int						GetClassType()							{ return m_classType; }
	virtual	CRuEntity*				GetRuEntity()							{ return m_pRuEntity; }

	virtual void					Show()									{ m_isVisible = true; }
	virtual void					Hide()									{ m_isVisible = false; }
	virtual	bool					IsVisible()								{ return m_isVisible; }	

	virtual	void					SetObjectType( SpriteObjectType type )	{ m_objectType = type; }
	virtual	int						GetObjectType()							{ return m_objectType; }
	virtual bool					SetObject( const char* act );
	virtual	void					SetPos( CRuVector3 &pos );
	virtual	CRuVector3				GetPos()								{ return m_nowPos; }
	virtual	void					SetDirection( CRuVector3 direction );
	virtual	void					SetDirection( float angle );
	virtual	CRuVector3				GetDirection()							{ return m_direction; }
	virtual void					SetMoveSpeed( float speed )				{ m_moveSpeed = speed; }
	virtual float					GetMoveSpeed()							{ return m_moveSpeed; }	

	virtual	void					SetScale(float scale);
	virtual	float					GetScale(float scale)					{ return m_scale; }

	// destruct
	virtual void					ClearDestruct();
	virtual void					SetDestructTime( float time );
	virtual float					GetDestructTime()						{ return m_destructTime; }
	virtual bool					IsDestruct()							{ return m_isDestruct; }

	// pause time
	virtual void					SetPauseTime( float time )				{ m_pauseTime = time; }
	virtual float					GetPauseTime()							{ return m_pauseTime; }	

	// event
	virtual	bool					PushEvent( int eventId, SpriteEventInfo& eventInfo );
	virtual	bool					FindEvent( int eventId );

	virtual	CRuEntity*				FindLinkEntity( int point );
	virtual bool					GetAttachPos( int point, CRuVector3& pos );

	// touch motion event
	virtual	void					MotionEvent( int type ) = 0;

protected:
	virtual	void					ReleaseEntity();
	virtual bool					PlayMotion( int id, int channel=0xFFFFFFFF, float blendTime=0.1f, bool forceReset=false );	
	virtual bool					IsMotionComplete();	
	virtual	void					AddOnEntity( bool isAttach, CRuEntity* pRuEntity, SpriteAttachPoint point );
	virtual	SpriteMoveDirection		ComputeDirection( CRuVector3 forward );	

protected:
	static	set<IBaseSprite*>			s_containers;				// 	
	static	CRuFontType*				s_pFontType;				// 字型資料
	static	CRuOptimalTerrain*			s_pRuTerrain;				// 地表資訊
	static	CRuFusion_Mime_Template*	s_pRuMimeTemplate;				//
	static	CRuFusion_Mime_Template*	s_pRuMimeTemplate_Deprecated;	//
	//static	CRuGlobalEventManager*	s_pRuEventListener;			// 動作事件
	static	int							s_mainPlayerId;

protected:
	// 3D Objects
	CRuEntity*						m_pRuEntity;				// entity 物件	
	int								m_objectType;				// 物件類型

	// other
	int								m_classType;				// 類別類型
	bool							m_isVisible;				// 顯示或隱藏
	int								m_id;						// 角色編號

	//
	float							m_scale;					// 縮放值

	// move
	CRuVector3						m_nowPos;					// 現在座標值
	CRuVector3						m_lastPos;					// 上一次座標值
	CRuVector3						m_direction;				// 朝向方向
	float							m_moveSpeed;				// 移動速度

	// motion
	int								m_firstMotion;				// 上半身動作
	int								m_secondMotion;				// 下半身動作	

	// event
	multimap<int, SpriteEventInfo>	m_event;

	// destruct 	
	bool							m_isDestruct;				//
	float							m_destructTime;				// 自我刪除時間

	// pause time
	float							m_pauseTime;				// 暫停處理時間
};

extern	CRuGlobalEventManager*		g_pRuGlobalEventManager;