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

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

namespace Mix{ namespace Tool{ namespace Dynamics{

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

HingeJoint::HingeJoint( Mix::Tool::Math::Vector^ axis, float lowerLimit, float upperLimit, bool collisionDisabled, float limitSpring, float limitDamper ) :
impl( NULL )
{
	impl = Mix::Tool::Win32::Dynamics::Factory::CreateHingeJoint( D3DXVECTOR3( axis->X, axis->Y, axis->Z ), D3DXToRadian( lowerLimit ), D3DXToRadian( upperLimit ), collisionDisabled, limitSpring, limitDamper );
	if( impl == NULL )
	{
		throw gcnew System::OutOfMemoryException();
	}
}

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

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

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

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

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

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

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

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

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

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

	float rad = D3DXToRadian( value );

	impl->SetLowerLimit( rad );
}

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

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

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

	float rad = D3DXToRadian( value );

	impl->SetUpperLimit( rad );
}

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

	return impl->GetLimitSpring();
}

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

	impl->SetLimitSpring( value );
}

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

	return impl->GetLimitDamper();
}

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

	impl->SetLimitDamper( value );
}
/*
float HingeJoint::NormalSpring::get( void )
{
	if( impl == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	return impl->GetNormalSpring();
}

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

	impl->SetNormalSpring( value );
}
*/

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

	return impl->GetCollisionDisabled();
}

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

	return impl->SetCollisionDisabled( value );
}

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

}}}
