#include <map>
#include "NetCli_MagicChild.h"
#include "../mainproc/GameMain.h"
#include "../Interface/debug/DebugMessage.h"

using namespace std;

struct NetMagicInfo
{
	int owner;
	int target;
	int id;
	float x, y, z;
	float destructTime;
	bool loop;
	CEffectSprite* explode;
	CLineEffectSprite* fly;
};

static map<int, NetMagicInfo>				g_netMagicInfo;

//-----------------------------------------------------------------------------
bool NetCli_MagicChild::_Init()
{
	if (This)
		return false;

	This = new NetCli_MagicChild;
	return NetCli_Magic::_Init();
}

//-----------------------------------------------------------------------------
bool NetCli_MagicChild::_Release()
{
	NetCli_Magic::_Release();
	if (This)
	{
		delete This;
		This = NULL;
	}
	return true;
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::_Update(float elapsed)
{
	vector<int> deleteArray;
	for ( map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.begin(); iter != g_netMagicInfo.end(); iter++ )
	{
		NetMagicInfo& info = iter->second;

		/*
		if ( info.fly )
		{
			switch ( info.fly->GetEffectMotionStep() )
			{
			//case eEffectMotion_Step_Disappear:
			case eEffectMotion_Step_Dead:
				if ( info.explode )
					info.explode->SetPauseTime(0.0f);
				break;
			}
		}
		*/

		info.destructTime -= elapsed;
		if ( info.destructTime < 0.0001f )
			deleteArray.push_back(iter->first);
	}

	for ( vector<int>::iterator iter = deleteArray.begin(); iter != deleteArray.end(); iter++ )
		g_netMagicInfo.erase(*iter);
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_BeginSpell( int OwnerID , int TargetID , float TargetX , float TargetY , float TargetZ , int MagicID , int SerialID )
{
	g_pDebugMessage->DebugOutput(0, "[R_BeginSpell] OwnerID %d TargetId %d MagicID%d SerialID%d", OwnerID , TargetID , MagicID, SerialID);
	CRoleSprite* sprite = NULL;

	NetMagicInfo info;
	info.id			= MagicID;
	info.owner		= OwnerID;
	info.target		= TargetID;
	info.x			= TargetX;
	info.y			= TargetY;
	info.z			= TargetZ;	
	info.fly		= NULL;
	info.explode	= NULL;
	info.loop		= false;
	info.destructTime	= 100.0f;

	g_netMagicInfo.insert( make_pair(SerialID, info) );
	if ( (sprite = g_pGameMain->FindRoleSprite(OwnerID)) != NULL )
		sprite->BeginSpell(MagicID);
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_EndSpell( int SerialID )
{
	g_pDebugMessage->DebugOutput(0, "[R_EndSpell] SerialID%d", SerialID);
	map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.find( SerialID );
	if ( iter != g_netMagicInfo.end() )
	{
		NetMagicInfo& info = iter->second;
		CRoleSprite* sprite = NULL;
		if ( (sprite = g_pGameMain->FindRoleSprite(info.owner)) != NULL )
			sprite->EndSpell();

		// 若命中特效是循環特效,改變流程
		if ( info.loop && info.explode )
		{
			switch ( info.explode->GetEffectMotionStep() )
			{
			case eEffectMotion_Step_Appear:
			case eEffectMotion_Step_Idle:
				info.explode->SetEffectMotionStep(eEffectMotion_Step_Disappear);
				break;
			}
		}

		info.destructTime = 6.0f;
	}
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_SysBeginShoot( int OwnerID , int TargetID , int MagicColID , int SerialID )
{
	g_pDebugMessage->DebugOutput(0, "[R_SysBeginShoot] OwnerID %d TargetId %d MagicID%d SerialID%d", OwnerID , TargetID , MagicColID, SerialID);

	NetMagicInfo info;
	info.id			= MagicColID;
	info.owner		= OwnerID;
	info.target		= TargetID;
	info.x			= 0.0f;
	info.y			= 0.0f;
	info.z			= 0.0f;	
	info.fly		= NULL;
	info.explode	= NULL;
	info.loop		= false;
	info.destructTime	= 1000.0f;

	g_netMagicInfo.insert( make_pair(SerialID, info) );
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_SysEndShoot( int SerialID )
{
	g_pDebugMessage->DebugOutput(0, "[R_SysEndShoot] SerialID%d", SerialID);
	map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.find( SerialID );
	if ( iter != g_netMagicInfo.end() )
	{
		NetMagicInfo& info = iter->second;
		info.destructTime = 6.0f;
	}
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_BeginShoot( int SerialID )
{
	g_pDebugMessage->DebugOutput(0, "[R_BeginShoot] SerialID%d", SerialID);
	map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.find( SerialID );
	if ( iter != g_netMagicInfo.end() )
	{
		NetMagicInfo& info = iter->second;
		GameObjDbStruct* itemDB = CNetGlobal::GetObj(info.id);
		if ( itemDB )
		{
			GameObjectRelationENUM relation = itemDB->MagicCol.TargetType;
			GameObjectImageStruct* gois = itemDB->ImageObj;
			CRoleSprite* owner = g_pGameMain->FindRoleSprite(info.owner);
			CRoleSprite* target = NULL;
			CRuVector3 pos;

			switch ( relation )
			{
			case EM_Releation_Locatoin:
				pos.Set(info.x, info.y, info.z);
				break;

			default:
				target = g_pGameMain->FindRoleSprite(info.target);
				break;
			}

			// 設定出手動作
			if ( owner )
				owner->CastSpell();

			// 飛行特效
			if ( strlen(gois->FlyACT) > 0 )
			{
				CLineEffectSprite* pFly = new CLineEffectSprite;
				if ( pFly->LoadRuEntity( gois->FlyACT ) )
				{
					pFly->SetEffectMotionStep( eEffectMotion_Step_Appear );
					pFly->SetPauseTime(0.5f);
					pFly->SetBeginSprite(owner, IBaseSprite::GetAttachPointEnum(gois->FlyBeginPoint));	
					pFly->SetMoveSpeed(32.0f);

					switch ( relation )
					{
					case EM_Releation_Locatoin:
						g_pDebugMessage->DebugOutput(0, "飛行特效不能沒有目標");
						break;

					default:
						pFly->SetRelative(target);
						pFly->SetAttachPoint(IBaseSprite::GetAttachPointEnum(gois->TargetPoint));
						break;
					}					
				}
				else
				{
					delete pFly;
					pFly = NULL;
				}

				info.fly = pFly;
			}

			// 命中特效
			if ( !info.loop && strlen(gois->ExplodeACT) > 1 )
			{
				CEffectSprite* pExplode = new CEffectSprite;
				if ( pExplode->LoadRuEntity( gois->ExplodeACT ) )
				{
					float delayTime = 0.5f;

					/*
					// 若有飛行特效，命中特效不立即撥放，需等到飛行特效結束時在撥放
					if ( info.fly )
						delayTime = 1000.0f;
					*/
					
					pExplode->SetPauseTime(delayTime);
					if ( pExplode->HasMotion(eMotion_Effect_Explode) )
						pExplode->SetEffectMotionStep(eEffectMotion_Step_Explode);
					else
					{
						info.loop = true;
						pExplode->SetEffectMotionStep(eEffectMotion_Step_Appear);
					}

					switch ( relation )
					{
					case EM_Releation_Locatoin:
						pExplode->SetPos(pos);
						break;

					default:
						pExplode->SetRelative(target);
						pExplode->SetAttachPoint(IBaseSprite::GetAttachPointEnum(gois->TargetPoint));
						break;
					}
				}
				else
				{
					delete pExplode;
					pExplode = NULL;
				}

				info.explode = pExplode;
			}
		}
	}
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_BeginSpellOK( int MagicID, int SerialID, int SpellTime )
{
	g_pDebugMessage->DebugOutput( 0, "[R_BeginSpellOK] MagicID %d ", MagicID );
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_BeginSpellFailed( int MagicID , int SerialID )
{
	g_pDebugMessage->DebugOutput( 0, "[R_BeginSpellFailed] MagicID %d ", MagicID );
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_MagicAttack( int MagicBaseID , int Serial , MagicAttackTypeENUM	AtkType , vector< MagicAtkEffectInfoStruct >& List )
{
	g_pDebugMessage->DebugOutput(0, "[R_MagicAttack] MagicBaseID%d Serial%d", MagicBaseID, Serial);
	map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.find( Serial );
	if ( iter != g_netMagicInfo.end() )
	{
		NetMagicInfo& info = iter->second;
		GameObjDbStruct* itemDB = CNetGlobal::GetObj(MagicBaseID);
		GameObjectImageStruct* gois = itemDB->ImageObj;

		// 延伸單體特效
		for ( vector<MagicAtkEffectInfoStruct>::iterator iter = List.begin(); iter != List.end(); iter++ )
		{
			CRoleSprite* target = g_pGameMain->FindRoleSprite(iter->GItemID);
			switch ( iter->Result )
			{
			case EM_MagicAtkResult_Normal:
			case EM_MagicAtkResult_Critial:
				if ( strlen(gois->ExtendACT) > 0 )
				{
					CEffectSprite* pExtend = new CEffectSprite;
					if ( pExtend->LoadRuEntity(gois->ExtendACT) )
					{
						pExtend->SetEffectMotionStep(eEffectMotion_Step_Explode);
						pExtend->SetRelative(target);
						pExtend->SetAttachPoint(IBaseSprite::GetAttachPointEnum(gois->ExtenPoint));
					}
					else
						delete pExtend;
				}
				break;

			case EM_MagicAtkResult_Miss:		// 未命中
			case EM_MagicAtkResult_NoEffect:	// 無效(免疫)
			case EM_MagicAtkResult_Absorb:		// 吸收
				break;
			}
		}
	}
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_MagicAssist( int MagicBaseID , int Serial , vector< MagicAssistEffectInfoStruct >& List )
{
	g_pDebugMessage->DebugOutput(0, "[R_MagicAssist] MagicBaseID%d Serial%d", MagicBaseID, Serial);
	map<int, NetMagicInfo>::iterator iter = g_netMagicInfo.find( Serial );
	if ( iter != g_netMagicInfo.end() )
	{
		NetMagicInfo& info = iter->second;
		GameObjDbStruct* itemDB = CNetGlobal::GetObj(MagicBaseID);
		GameObjectImageStruct* gois = itemDB->ImageObj;

		// 延伸單體特效
		for ( vector<MagicAssistEffectInfoStruct>::iterator iter = List.begin(); iter != List.end(); iter++ )
		{
			CRoleSprite* target = g_pGameMain->FindRoleSprite(iter->GItemID);
			switch ( iter->Result )
			{
			case EM_MagicAtkResult_Normal:
			case EM_MagicAtkResult_Critial:
				if ( strlen(gois->ExtendACT) > 0 )
				{
					CEffectSprite* pExtend = new CEffectSprite;
					if ( pExtend->LoadRuEntity(gois->ExtendACT) )
					{
						pExtend->SetEffectMotionStep(eEffectMotion_Step_Explode);
						pExtend->SetRelative( target );
						pExtend->SetAttachPoint( IBaseSprite::GetAttachPointEnum(gois->TargetPoint) );
					}
					else
						delete pExtend;
				}
				if ( iter->EffectTime != 0 )
					R_AddBuffInfo( iter->GItemID, MagicBaseID, iter->EffectTime );
				break;

			case EM_MagicAtkResult_Miss:		// 未命中
			case EM_MagicAtkResult_NoEffect:	// 無效(免疫)
			case EM_MagicAtkResult_Absorb:		// 吸收
				break;
			}
		}
	}
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_FixAssistMagicTime ( int MagicID , int EffectTime )
{
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_CancelSpellMagic   ( int OwnerID , int SerialID )
{
	g_pDebugMessage->DebugOutput( 0, "[R_CancelSpellMagic] (取消失法 失法中斷)OwnerID %d ", OwnerID );
	R_EndSpell(SerialID);
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_SetMagicPointResult( int MagicID , int MagicPos , bool Result , int ErrorCode )
{
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_AddBuffInfo( int OwnerID , int MagicID , int EffectTime )
{
	g_pDebugMessage->DebugOutput( 0, "[R_AddBuffInfo] OwnerID=%d MagicID=%d EffectTime=%d", OwnerID, MagicID, EffectTime );

	CRoleSprite* sprite = g_pGameMain->FindRoleSprite( OwnerID );
	if ( sprite )
	{
		sprite->AddBuff( MagicID, (float)EffectTime );
	}	
}

//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_DelBuffInfo( int OwnerID , int MagicID )
{
	g_pDebugMessage->DebugOutput( 0, "[R_DelBuffInfo] OwnerID=%d MagicID=%d", OwnerID, MagicID );

	CRoleSprite* sprite = g_pGameMain->FindRoleSprite( OwnerID );
	if ( sprite )
	{
		sprite->EraseBuff( MagicID );
	}	
}
//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_ResetColdown		  ( )
{ 
	RoleDataEx* Owner = CNetGlobal::RoleData();
	Owner->BaseData.Coldown.Init();
};
//-----------------------------------------------------------------------------
void NetCli_MagicChild::R_MagicShieldInfo( int AttackGUID , int UnAttackGUID , int AttackMagicID , int ShieldMagicID , int AbsobDamage )
{
	g_pDebugMessage->DebugOutput( 0, "[R_MagicShieldInfo] AttackGUID=%d UnAttackGUID=%d AbsobDamage=%d", AttackGUID, UnAttackGUID, AbsobDamage );

}
//-----------------------------------------------------------------------------