#include "Mix/Tool/CLR/Core/Dynamics/BallJoint.h"

#include "Mix/Tool/Win32/Core/Dynamics/Factory.h"
#include "Mix/Tool/Win32/Core/Dynamics/BallJoint.h"

namespace Mix{ namespace Tool{ namespace Dynamics{

BallJoint::BallJoint( void ) :
impl( NULL )
{
	impl = Mix::Tool::Win32::Dynamics::Factory::CreateBallJoint();
	if( impl == NULL )
	{
		throw gcnew System::OutOfMemoryException();
	}
}

BallJoint::BallJoint(	Mix::Tool::Math::Vector^ swingAxis,
						Mix::Tool::Math::Vector^ twistAxis,
						float swingLimit1,
						float swingLimit2,
						float twistLimit,
						bool collisionDisabled,
						float spring,
						float damper,
						float limitSpring,
						float limitDamper ) :
impl( NULL )
{
	D3DXVECTOR3 sa( swingAxis->X, swingAxis->Y, swingAxis->Z );
	D3DXVECTOR3 ta( twistAxis->X, twistAxis->Y, twistAxis->Z );

	impl = Mix::Tool::Win32::Dynamics::Factory::CreateBallJoint( sa, ta, D3DXToRadian( swingLimit1 ), D3DXToRadian( swingLimit2 ), D3DXToRadian( twistLimit ), collisionDisabled, spring, damper, limitSpring, limitDamper );
	if( impl == NULL )
	{
		throw gcnew System::OutOfMemoryException();
	}
}

BallJoint::~BallJoint( void )
{
	if( impl != NULL )
	{
		delete impl;
		impl = NULL;
	}
}

Mix::Tool::Math::Vector^ BallJoint::SwingAxis::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3& axis = impl->GetSwingAxis();

	return gcnew Mix::Tool::Math::Vector( axis.x, axis.y, axis.z );
}

void BallJoint::SwingAxis::set( Mix::Tool::Math::Vector^ value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	if( value == nullptr )
	{
		throw gcnew System::Exception( L"SwingAxis" );
	}

	impl->SetSwingAxis( D3DXVECTOR3( value->X, value->Y, value->Z ) );
}

Mix::Tool::Math::Vector^ BallJoint::TwistAxis::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	const D3DXVECTOR3& axis = impl->GetTwistAxis();

	return gcnew Mix::Tool::Math::Vector( axis.x, axis.y, axis.z );
}

void BallJoint::TwistAxis::set( Mix::Tool::Math::Vector^ value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	if( value == nullptr )
	{
		throw gcnew System::Exception( L"TwistAxis" );
	}

	impl->SetTwistAxis( D3DXVECTOR3( value->X, value->Y, value->Z ) );
}

float BallJoint::SwingLimit1::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return D3DXToDegree( impl->GetSwingLimit1() );
}

void BallJoint::SwingLimit1::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetSwingLimit1( D3DXToRadian( value ) );
}

float BallJoint::SwingLimit2::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return D3DXToDegree( impl->GetSwingLimit2() );
}

void BallJoint::SwingLimit2::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetSwingLimit2( D3DXToRadian( value ) );
}

float BallJoint::TwistLimit::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return D3DXToDegree( impl->GetTwistLimit() );
}

void BallJoint::TwistLimit::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetTwistLimit( D3DXToRadian( value ) );
}

float BallJoint::Spring::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetSpring();
}

void BallJoint::Spring::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetSpring( value );
}

float BallJoint::Damper::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetDamper();
}

void BallJoint::Damper::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetDamper( value );
}

float BallJoint::LimitSpring::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetLimitSpring();
}

void BallJoint::LimitSpring::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetLimitSpring( value );
}

float BallJoint::LimitDamper::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetLimitDamper();
}

void BallJoint::LimitDamper::set( float value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	impl->SetLimitDamper( value );
}

bool BallJoint::CollisionDisabled::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetCollisionDisabled();
}

void BallJoint::CollisionDisabled::set( bool value )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->SetCollisionDisabled( value );
}

Mix::Tool::Win32::Dynamics::Joint* BallJoint::Impl::get( void )
{
	return impl;
}

}}}
