#include "Mix/Private/Scene/Common/LibertyCollider.h"

#include "Mix/Private/Dynamics/RigidBody.h"
#include "Mix/Scene/IRendererObject.h"

namespace Mix{ namespace Scene{ namespace Common{

LibertyCollider* LibertyCollider::CreateInstance( Mix::Scene::IRendererObject* pOwner )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SCENE, LibertyCollider, pOwner );
}

LibertyCollider::LibertyCollider( Mix::Scene::IRendererObject* pOwner ) :
m_pOwner( NULL ),
m_pRigidBody( NULL )
{
	MIX_ASSERT( pOwner != NULL );
	m_pOwner = pOwner;
}

LibertyCollider::~LibertyCollider( void )
{
	MIX_ASSERT( m_pOwner == NULL );
	MIX_RELEASE( m_pRigidBody );
}

Boolean LibertyCollider::Initialize( Mix::Dynamics::IShape* pShape, const wchar_t* pDebugName )
{
	MIX_ASSERT( pShape != NULL );
	MIX_ASSERT( pDebugName != NULL );
	MIX_ASSERT( m_pRigidBody == NULL );

	m_pRigidBody = Mix::Dynamics::RigidBody::CreateInstance( 0.0f, pShape );
	if( m_pRigidBody != NULL )
	{
		if( m_pRigidBody->Initialize( pDebugName ) == True )
		{
			DynamicsObject::Initialize( this );
		}
		else
		{
			return False;
		}
	}
	else
	{
		return False;
	}

	return True;
}

void LibertyCollider::Dispose( void )
{
	m_pOwner = NULL;
}

Mix::Dynamics::IRigidBody* LibertyCollider::GetInternalRigidBodyPtr( void ) const
{
	MIX_ASSERT( m_pRigidBody != NULL );

	return m_pRigidBody;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::Common::DynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Dynamics::IObject* LibertyCollider::GetInternalObjectPtr( void ) const
{
	return m_pRigidBody;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::ILibertyCollider
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean LibertyCollider::IsSimulationEnabled( void ) const
{
	return m_pRigidBody->IsSimulationEnabled();
}

void LibertyCollider::SetSimulationEnabled( Boolean state )
{
	m_pRigidBody->SetSimulationEnabled( state );
}

Mix::Dynamics::IRigidBody::STATUS LibertyCollider::GetStatus( void ) const
{
	return m_pRigidBody->GetStatus();
}

Boolean LibertyCollider::SetStatus( Mix::Dynamics::IRigidBody::STATUS status )
{
	return m_pRigidBody->SetStatus( status );
}

UInt16 LibertyCollider::GetFilterGroup( void ) const
{
	return m_pRigidBody->GetFilterGroup();
}

void LibertyCollider::SetFilterGroup( UInt16 filterGroup )
{
	m_pRigidBody->SetFilterGroup( filterGroup );
}

UInt16 LibertyCollider::GetFilterMask( void ) const
{
	return m_pRigidBody->GetFilterMask();
}

void LibertyCollider::SetFilterMask( UInt16 filterMask )
{
	m_pRigidBody->SetFilterMask( filterMask );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IKineticCollider
////////////////////////////////////////////////////////////////////////////////////////////////////

Float32 LibertyCollider::GetMass( void ) const
{
	return m_pRigidBody->GetMass();
}

void LibertyCollider::SetMass( Float32 mass )
{
	m_pRigidBody->SetMass( mass );
}

const Mix::Dynamics::MATERIAL& LibertyCollider::GetMaterial( void ) const
{
	return m_pRigidBody->GetMaterial();
}

void LibertyCollider::SetMaterial( const Mix::Dynamics::MATERIAL& material )
{
	m_pRigidBody->SetMaterial( material );
}

Boolean LibertyCollider::IsAlwaysActive( void ) const
{
	return m_pRigidBody->IsAlwaysActive();
}

Boolean LibertyCollider::SetAlwaysActive( Boolean state )
{
	return m_pRigidBody->SetAlwaysActive( state );
}

Boolean LibertyCollider::IsActive( void ) const
{
	return ( ( m_pRigidBody->IsInWorld() == True ) && ( m_pRigidBody->IsActive() == True ) );
}

Boolean LibertyCollider::Activate( void )
{
	return m_pRigidBody->Activate();
}

Boolean LibertyCollider::Deactivate( Boolean bForce )
{
	return m_pRigidBody->Deactivate( bForce );
}

Mix::Vector3 LibertyCollider::GetLinearFactor( void ) const
{
	return m_pRigidBody->GetLinearFactor();
}

void LibertyCollider::SetLinearFactor( const Mix::Vector3& factor )
{
	m_pRigidBody->SetLinearFactor( factor );
}

Float32 LibertyCollider::GetLinearDamping( void ) const
{
	return m_pRigidBody->GetLinearDamping();
}

void LibertyCollider::SetLinearDamping( Float32 damping )
{
	m_pRigidBody->SetLinearDamping( damping );
}

Mix::Vector3 LibertyCollider::GetLinearVelocity( void )
{
	return m_pRigidBody->GetLinearVelocity();
}

Boolean LibertyCollider::SetLinearVelocity( const Mix::Vector3& velocity )
{
	return m_pRigidBody->SetLinearVelocity( velocity );
}

Float32 LibertyCollider::GetLinearSleepingThresholds( void ) const
{
	return m_pRigidBody->GetLinearSleepingThresholds();
}

void LibertyCollider::SetLinearSleepingThresholds( Float32 thresholds )
{
	m_pRigidBody->SetLinearSleepingThresholds( thresholds );
}

Mix::Vector3 LibertyCollider::GetAngularFactor( void ) const
{
	return m_pRigidBody->GetAngularFactor();
}

void LibertyCollider::SetAngularFactor( const Mix::Vector3& factor )
{
	m_pRigidBody->SetAngularFactor( factor );
}

Float32 LibertyCollider::GetAngularDamping( void ) const
{
	return m_pRigidBody->GetAngularDamping();
}

void LibertyCollider::SetAngularDamping( Float32 damping )
{
	m_pRigidBody->SetAngularDamping( damping );
}

Mix::Vector3 LibertyCollider::GetAngularVelocity( void )
{
	return m_pRigidBody->GetAngularVelocity();
}

Boolean LibertyCollider::SetAngularVelocity( const Mix::Vector3& velocity )
{
	return m_pRigidBody->SetAngularVelocity( velocity );
}

Float32 LibertyCollider::GetAngularSleepingThresholds( void ) const
{
	return m_pRigidBody->GetAngularSleepingThresholds();
}

void LibertyCollider::SetAngularSleepingThresholds( Float32 thresholds )
{
	m_pRigidBody->SetAngularSleepingThresholds( thresholds );
}

Boolean LibertyCollider::ApplyLinearImpulse( const Mix::Vector3& impulse )
{
	return m_pRigidBody->ApplyLinearImpulse( impulse );
}

Boolean LibertyCollider::ApplyAngularImpulse( const Mix::Vector3& impulse )
{
	return m_pRigidBody->ApplyAngularImpulse( impulse );
}

Boolean LibertyCollider::ApplyImpulse( const Mix::Vector3& impulse, const Mix::Vector3& pos )
{
	return m_pRigidBody->ApplyImpulse( impulse, pos );
}

Mix::Vector3 LibertyCollider::GetTotalLinearForce( void )
{
	return m_pRigidBody->GetTotalLinearForce();
}

Mix::Vector3 LibertyCollider::GetTotalAngularForce( void )
{
	return m_pRigidBody->GetTotalAngularForce();
}

Boolean LibertyCollider::ApplyLinearForce( const Mix::Vector3& force )
{
	return m_pRigidBody->ApplyLinearForce( force );
}

Boolean LibertyCollider::ApplyAngularForce( const Mix::Vector3& force )
{
	return m_pRigidBody->ApplyAngularForce( force );
}

Boolean LibertyCollider::ApplyForce( const Mix::Vector3& force, const Mix::Vector3& pos )
{
	return m_pRigidBody->ApplyForce( force, pos );
}

void LibertyCollider::ClearForce( void )
{
	m_pRigidBody->ClearForce();
}

void LibertyCollider::ClearMotion( void )
{
	m_pRigidBody->ClearMotion();
}

void LibertyCollider::ClearMotion( const Mix::Quaternion& rot, const Mix::Vector3& pos )
{
	m_pRigidBody->ClearMotion( rot, pos );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::ICollider
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean LibertyCollider::IsDefault( void ) const
{
	return ( m_pRigidBody->GetStatus() == Mix::Dynamics::IRigidBody::DEFAULT );
}

Boolean LibertyCollider::IsStatic( void ) const
{
	return ( m_pRigidBody->GetStatus() == Mix::Dynamics::IRigidBody::STATIC );
}

Boolean LibertyCollider::IsKinematic( void ) const
{
	return ( m_pRigidBody->GetStatus() == Mix::Dynamics::IRigidBody::KINEMATIC );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDynamicsObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDynamicsObject::TYPE LibertyCollider::GetType( void ) const
{
	return Mix::Scene::IDynamicsObject::LIBERTY_COLLIDER;
}

Boolean LibertyCollider::GetOwner( Mix::Scene::IRendererObject** ppOwner )
{
	if( m_pOwner != NULL )
	{
		MIX_ADD_REF( m_pOwner );
		( *ppOwner ) = m_pOwner;
	}
	else
	{
		return False;
	}

	return True;
}

Mix::Scene::IRendererObject* LibertyCollider::GetOwnerPtr( void ) const
{
	return m_pOwner;
}

Mix::Matrix4x4 LibertyCollider::GetWorldMatrix( void ) const
{
	return m_pRigidBody->GetWorldMatrix();
}

Mix::Quaternion LibertyCollider::GetWorldRotation( void ) const
{
	return m_pRigidBody->GetWorldRotation();
}

Mix::Vector3 LibertyCollider::GetWorldPosition( void ) const
{
	return m_pRigidBody->GetWorldPosition();
}

Boolean LibertyCollider::HasContactListener( void ) const
{
	return DynamicsObject::HasContactListener();
}

Boolean LibertyCollider::ContainsContactListener( Mix::Scene::IContactListener* pListener ) const
{
	return DynamicsObject::ContainsContactListener( pListener );
}

Boolean LibertyCollider::AddContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::AddContactListener( pListener );
}

Boolean LibertyCollider::RemoveContactListener( Mix::Scene::IContactListener* pListener )
{
	return DynamicsObject::RemoveContactListener( pListener );
}

void LibertyCollider::ClearContactListener( void )
{
	DynamicsObject::ClearContactListener();
}

Int32 LibertyCollider::GetUserIndex( void )  const
{
	return DynamicsObject::GetUserIndex();
}

void LibertyCollider::SetUserIndex( Int32 index )
{
	DynamicsObject::SetUserIndex( index );
}

void* LibertyCollider::GetUserPtr( void ) const
{
	return DynamicsObject::GetUserPtr();
}

void LibertyCollider::SetUserPtr( void* ptr )
{
	DynamicsObject::SetUserPtr( ptr );
}

}}}
