#include <windows.h>
#include "sprite.h"
#include "../ErrorList/errorlist.h"

//-----------------------------------------------------------------------------
CEffectSprite::CEffectSprite()
{
	m_classType			= eSpriteClass_Effect;
	m_pRelative			= NULL;
	m_offset.m_x		= 0.0f;
	m_offset.m_y		= 0.0f;
	m_offset.m_z		= 0.0f;
	m_attachPoint		= eAttach_Null;
	m_effectMotionStep	= eEffectMotion_Step_Null;	
	m_isAutoDestruct	= true;
	m_pBegin			= NULL;
	m_beginPoint		= eAttach_Null;

	memset( &m_damage, 0, sizeof(m_damage) );
}

//-----------------------------------------------------------------------------
void CEffectSprite::ReceiveDestruct(IBaseSprite* pSprite)
{
	if (pSprite == m_pRelative)
	{
		m_pRelative = NULL;
		SetDestructTime(0.5f);
	}
}

//-----------------------------------------------------------------------------
void CEffectSprite::Update(float elapsed)
{
	CRuVector3 pos;

	m_effectStepTime += elapsed;

	switch ( m_effectMotionStep )
	{
	case eEffectMotion_Step_Appear:
		if ( IsMotionComplete() )
			SetEffectMotionStep(eEffectMotion_Step_Idle);
		break;

	case eEffectMotion_Step_Idle:
		break;

	case eEffectMotion_Step_Disappear:
		if ( IsMotionComplete() || m_effectStepTime > 5.0f )
			SetEffectMotionStep( eEffectMotion_Step_Dead );
		break;

	case eEffectMotion_Step_Explode:
		if (m_effectStepTime == 0.0f)
			MotionEvent(ruENTITYEVENT_HIT);

		if ( IsMotionComplete() )
			SetEffectMotionStep( eEffectMotion_Step_Dead );
		break;

	case eEffectMotion_Step_Dead:
		break;
	}

	// 初始出現座標
	if ( m_pBegin )
	{
		m_pBegin->GetAttachPos(m_beginPoint, pos);
		SetPos(pos);
		m_pBegin = NULL;
		m_beginPoint = eAttach_Null;
	}

	// 設定特效物件座標
	if ( m_pRelative )
	{
		m_pRelative->GetAttachPos(m_attachPoint, pos);
		if ( m_attachPoint == eAttach_Freeze_Down )
		{			
			SetRelative(NULL);
			SetAttachPoint(eAttach_Null);
		}
	}
	else
		pos = m_nowPos;
		
	SetEffectPos(pos + m_offset, elapsed);
	IBaseSprite::Update(elapsed);
}

//-----------------------------------------------------------------------------
void CEffectSprite::MotionEvent( int type )
{
	switch ( type )
	{
	case ruENTITYEVENT_HIT:
		{
			ShowDamage();
			/*
			CRoleSprite* pAttackSprite = dynamic_cast<CRoleSprite*>(m_pBegin);
			CRoleSprite* pUnderSprite = dynamic_cast<CRoleSprite*>(m_pRelative);

			if ( pUnderSprite )
			{
				// 是否產生跳血
				if ( s_mainPlayerId == pUnderSprite->GetIdentify() )
				{
					if ( m_damageHp < 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageHp, 0xFFEF10EF );
					else if ( m_damageHp > 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageHp, 0xFF10EF10 );

					if ( m_damageMp < 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageMp, 0xFF1090DF );
					else if ( m_damageMp > 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageMp, 0xFF1010EF );
				}

				// 通知受攻擊者動作
				if ( m_damageHp < 0 )
				{
					if ( !pUnderSprite->IsDead() )
						pUnderSprite->SetAction( eAction_Hurt );
				}
			}

			if ( pAttackSprite )
			{
				// 是否產生跳血
				if ( s_mainPlayerId == pAttackSprite->GetIdentify() )
				{
					if ( m_damageHp < 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageHp, 0xFFEF10EF );
					else if ( m_damageHp > 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageHp, 0xFF10EF10 );

					if ( m_damageMp < 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageMp, 0xFF1090DF );
					else if ( m_damageMp > 0 )
						pUnderSprite->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damageMp, 0xFF1010EF );
				}
			}
			*/
		}
		break;
	}
}

//-----------------------------------------------------------------------------
void CEffectSprite::SetEffectPos(CRuVector3& pos, float elapsed)
{
	IBaseSprite::SetPos(pos);
}

//-----------------------------------------------------------------------------
void CEffectSprite::ShowDamage()
{
	/*
	if ( m_damage.type == eEffectDamageType_Null )
		return;

	CRoleSprite* src = dynamic_cast<CRoleSprite*>(m_pBegin);
	CRoleSprite* dest = dynamic_cast<CRoleSprite*>(m_pRelative);

	if ( dest )
	{		
		// 
		if ( s_mainPlayerId == dest->GetIdentify() )
		{
			switch( m_damage.type )
			{
			case eEffectDamageType_HP:
				switch( m_damage.state )
				{
				case eEffectDamageState_Normal:
					if ( m_damage.value < 0 )
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFFEF10EF );
					else
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF10EF10 );
					break;

				case eEffectDamageState_Miss:
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
					break;
				}
				break;

			case eEffectDamageType_MP:
				switch( m_damage.state )
				{
				case eEffectDamageState_Normal:
					if ( m_damage.value < 0 )
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF1090DF );
					else
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF1010EF );
					break;

				case eEffectDamageState_Miss:
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
					break;
				}
				break;

			case eEffectDamageType_SP:
				switch( m_damage.state )
				{
				case eEffectDamageState_Normal:
					if ( m_damage.value < 0 )
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFFEF10EF );
					else
						dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF10EF10 );
					break;

				case eEffectDamageState_Miss:
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
					break;
				}
				break;
			}
		}

		if ( m_damage.type == eEffectDamageType_HP && m_damage.value < 0 && !dest->GetDeadState() )
		{
			//dest->SetAction( eAction_Hurt );
		}
	}

	if ( src && s_mainPlayerId == src->GetIdentify() )
	{
		switch( m_damage.type )
		{
		case eEffectDamageType_HP:
			switch( m_damage.state )
			{
			case eEffectDamageState_Normal:
				if ( m_damage.value < 0 )
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFFEF10EF );
				else
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF10EF10 );
				break;

			case eEffectDamageState_Miss:
				dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
				break;
			}
			break;

		case eEffectDamageType_MP:
			switch( m_damage.state )
			{
			case eEffectDamageState_Normal:
				if ( m_damage.value < 0 )
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF1090DF );
				else
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF1010EF );
				break;

			case eEffectDamageState_Miss:
				dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
				break;
			}
			break;

		case eEffectDamageType_SP:
			switch( m_damage.state )
			{
			case eEffectDamageState_Normal:
				if ( m_damage.value < 0 )
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFFEF10EF );
				else
					dest->ShowDmgText( EM_ATTACK_DMGTYPE_NORMAL, m_damage.value, 0xFF10EF10 );
				break;

			case eEffectDamageState_Miss:
				dest->ShowDmgText( EM_ATTACK_DMGTYPE_MISS, m_damage.value, 0xFFFFFFFF );
				break;
			}
			break;
		}
	}
	*/
}

//-----------------------------------------------------------------------------
void CEffectSprite::SetEffectMotionStep( int step )
{	
	m_effectMotionStep = step;
	m_effectStepTime = 0.0f;

	switch (m_effectMotionStep)
	{
	case eEffectMotion_Step_Appear:		
		if ( !PlayMotion( eMotion_Effect_Appear ) )
			SetEffectMotionStep( eEffectMotion_Step_Idle );
		break;

	case eEffectMotion_Step_Idle:
		if ( !PlayMotion( eMotion_Effect_Idle ) )
			SetEffectMotionStep( eEffectMotion_Step_Disappear );
		break;

	case eEffectMotion_Step_Disappear:
		if ( !PlayMotion( eMotion_Effect_Disappear ) )
			SetEffectMotionStep( eEffectMotion_Step_Dead );
		break;

	case eEffectMotion_Step_Explode:
		if ( !PlayMotion( eMotion_Effect_Explode ) )
			SetEffectMotionStep( eEffectMotion_Step_Dead );		
		break;

	case eEffectMotion_Step_Dead:
		if ( m_isAutoDestruct )
			SetDestructTime(2.5f);
		break;
	}
}

//-----------------------------------------------------------------------------
void CEffectSprite::SetBeginSprite(IBaseSprite* begin, int point)
{
	m_pBegin = begin;
	m_beginPoint = point;
}

//-----------------------------------------------------------------------------
void CEffectSprite::SetMagicInfo( int id, int type, int state, int value )
{
	m_damage.magicId	= id;
	m_damage.type		= type;
	m_damage.state		= state;
	m_damage.value		= value;
}

//-----------------------------------------------------------------------------
CLineEffectSprite::CLineEffectSprite()
{
	m_classType			= eSpriteClass_Effect_Line;
	m_flyDelta			= 0.0f;

	m_attachExplode.clear();
	m_flyVector.Set(0.0f, 0.0f, 0.0f);
	//m_pExplode			= NULL;
}

//-----------------------------------------------------------------------------
CLineEffectSprite::~CLineEffectSprite()
{
	ReleaseExplode();
}

//-----------------------------------------------------------------------------
void CLineEffectSprite::ReceiveDestruct(IBaseSprite* pSprite)
{
	CEffectSprite::ReceiveDestruct(pSprite);
}

//-----------------------------------------------------------------------------
void CLineEffectSprite::AttachExplodeEffect( CEffectSprite* pExplode )
{
	/*
	ReleaseExplode();

	if ( pExplode )
	{
		m_pExplode = pExplode;
		m_pExplode->SetPauseTime( 10000.0f );
	}
	*/
}

//-----------------------------------------------------------------------------
void CLineEffectSprite::ReleaseExplode()
{
	/*
	for ( vector<CEffectSprite*>::iterator iter = m_attachExplode.begin(); iter != m_attachExplode.end(); iter++ )
	{
		iter

	}

	vector<CEffectSprite*>			m_attachExplode;				// 串接爆炸特效

	if ( m_pExplode )
	{
		m_pExplode->SetDestructTime(0.0f);
		m_pExplode = NULL;
	}
	*/
}

//-----------------------------------------------------------------------------
void CLineEffectSprite::SetEffectPos(CRuVector3& pos, float elapsed)
{
	switch(m_effectMotionStep)
	{
	case eEffectMotion_Step_Appear:
		break;

	case eEffectMotion_Step_Idle:
	case eEffectMotion_Step_Explode:
		while( elapsed > 0.0f )
		{
			CRuVector3 dir	= m_nowPos - pos;
			float dis		= dir.Magnitude();
			float time		= min(elapsed, 0.1f);
			float move		= (m_moveSpeed + m_flyDelta) * time;

			SetDirection(dir);
			if ( dis < 16.0f )
			{
				elapsed = 0.0f;
				SetPos(pos);
				SetEffectMotionStep( eEffectMotion_Step_Disappear );
			}
			else
			{				
				elapsed -= 0.1f;
				m_flyDelta += time * 128.0f;
				SetPos(m_nowPos - dir * (move / dis));
			}
		}

		break;

	case eEffectMotion_Step_Disappear:
	case eEffectMotion_Step_Dead:
		SetPos(pos);
		break;
	}
}