///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_InventoryTool_Tequila.h
// Author : Will Plano
// Date   : 03/03/2009
//
// Copyright (C) 2009 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Inventory/Items/Weapons/Tools/AVP_InventoryTequila_ClientEffectsHandler.h"

#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ClientActor_Human.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"

AVP_InventoryTequila_ClientEffectsHandler::AVP_InventoryTequila_ClientEffectsHandler( const Asura_Hash_ID uHash, const Asura_Guid uOwnerGuid )
: PARENT( uHash, uOwnerGuid )
{
	
}

AVP_InventoryTequila_ClientEffectsHandler::~AVP_InventoryTequila_ClientEffectsHandler()
{
	m_xIKSolver.Shutdown();
}

Asura_Animation* AVP_InventoryTequila_ClientEffectsHandler::CreateAnimation()
{
	const AVP_ClientActor_Human* pxMyClient = AVP_ClientActor_Human::FindEntity( m_uOwnerGuid );
	const AVP_ClientActor_Human* pxTheirClient = pxMyClient ? AVP_ClientActor_Human::FindEntity( pxMyClient->GetPickedUpBuddyGuid() ) : NULL;
	Asura_Assert( pxTheirClient && pxTheirClient->GetAnimation(), "Unable to find human animation to nab skin off" );
	if ( pxTheirClient && pxTheirClient->GetAnimation() )
	{
		Asura_Hash_ID uSkin0 = pxTheirClient->GetAnimation()->GetSkinHashID( 0 );
		Asura_Hash_ID uSkin1 = pxTheirClient->GetAnimation()->GetSkinHashID( 1 );
		Asura_Hash_ID uSkin2 = pxTheirClient->GetAnimation()->GetSkinHashID( 2 );

		Asura_Assert( m_pxAnimation == NULL, "Already got an animation" );
		m_pxAnimation = new Asura_Animation( uSkin0 );
		m_pxAnimation->SetSkin( uSkin1, false, 1 );
		m_pxAnimation->SetSkin( uSkin2, false, 2 );

		InitialiseAnimation();

		return m_pxAnimation;
	}
	return NULL;
}

static const Asura_AVector3	g_xDownVector( 0.0f, 1.0f, 0.0f );
static const int NUM_EXCEPTIONS = 7;
static const u_short s_ausClassificationExceptionArray[NUM_EXCEPTIONS] = { 
	AVP_ENTITYCLASS_DISC,
	AVP_ENTITYCLASS_DROPSHIP_MISSILE,
	AVP_ENTITYCLASS_GENERICPROJECTILE,
	AVP_ENTITYCLASS_HUMANFLARE,
	AVP_ENTITYCLASS_PROJECTILE_FLAMETHROWER,
	AVP_ENTITYCLASS_MINE,
	AVP_ENTITYCLASS_PROJECTILE_ACIDSPIT
};

void AVP_InventoryTequila_ClientEffectsHandler::InitialiseAnimation()
{
	if ( m_pxAnimation )
	{
		Asura_Assert( m_xIKSolver.GetFirstChain() == NULL, "IK Solver already initialised, clearing it..." );
		if ( m_xIKSolver.GetFirstChain() )
		{
			m_xIKSolver.Clear();
		}

		// Setup Left arm IK
		m_xLeftArmIKChain.SetBonesArrays( AVP_Human_Description::GetThirdPersonLeftArmChainBonesArray(), AVP_Human_Description::GetThirdPersonLeftArmChainTwistBonesArray() );
		if ( m_pxAnimation && m_pxAnimation->GetSkin() )
		{
			m_xLeftArmIKChain.SetAxesFromRestPose( m_pxAnimation->GetSkin()->BoneRestPose );
		}
		m_xLeftArmIKChain.SetAttractive( 0.9f );
		m_xLeftArmIKChain.SetDrag( 0.75f );
		m_xLeftArmIKChain.SetDoJointConstraints();
		m_xLeftArmIKChain.SetBoneCollisionRadius( 0.1f );
		m_xIKSolver.AddChain( m_xLeftArmIKChain );

		m_xLeftLegIKChain.SetWorldSpaceLOSDirection( g_xDownVector );
		m_xLeftLegIKChain.SetTestAgainstEverything( m_uOwnerGuid );
		m_xLeftLegIKChain.SetExclusionLists(  NUM_EXCEPTIONS, s_ausClassificationExceptionArray );
		m_xLeftLegIKChain.SetBonesArrays( AVP_Human_Description::GetThirdPersonLeftLegChainBonesArray() );
		if ( m_pxAnimation && m_pxAnimation->GetSkin() )
		{
			m_xLeftLegIKChain.SetAxesFromRestPose( m_pxAnimation->GetSkin()->BoneRestPose );
		}
		m_xLeftLegIKChain.SetExtendLimit( 0.01f );
		m_xIKSolver.AddChain( m_xLeftLegIKChain );

		m_xRightLegIKChain.SetWorldSpaceLOSDirection( g_xDownVector );
		m_xRightLegIKChain.SetTestAgainstEverything( m_uOwnerGuid );
		m_xRightLegIKChain.SetExclusionLists(  NUM_EXCEPTIONS, s_ausClassificationExceptionArray );
		m_xRightLegIKChain.SetBonesArrays( AVP_Human_Description::GetThirdPersonRightLegChainBonesArray() );
		if ( m_pxAnimation && m_pxAnimation->GetSkin() )
		{
			m_xRightLegIKChain.SetAxesFromRestPose( m_pxAnimation->GetSkin()->BoneRestPose );
		}
		m_xRightLegIKChain.SetExtendLimit( 0.01f );
		m_xIKSolver.AddChain( m_xRightLegIKChain );

		m_pxAnimation->SetIKSolver( &m_xIKSolver );
		m_xIKSolver.Enable();
	}
}
