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

#include <vector>

#include "Mix/Tool/Win32/Core/Dynamics/Impl/World.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/StaticPlane.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/StaticMesh.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/BoxShape.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/CapsuleShape.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/SphereShape.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/CompoundShape.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/PointJoint.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/HingeJoint.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/BallJoint.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/RigidBody.h"
#include "Mix/Tool/Win32/Core/Dynamics/Impl/KinematicCharacter.h"
#include "Mix/Tool/Win32/Core/Dynamics/Design/Actor.h"
#include "Mix/Tool/Win32/Core/Dynamics/Design/Terrain.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{

Mix::Tool::Win32::Dynamics::World* Factory::CreateWorld( void )
{
	Mix::Tool::Win32::Dynamics::Impl::World* pWorld = new Mix::Tool::Win32::Dynamics::Impl::World();

	if( pWorld != NULL )
	{
		if( pWorld->Initialize() == false )
		{
			MIX_DELETE( pWorld );
		}
	}

	return pWorld;
}

Mix::Tool::Win32::Dynamics::StaticPlane* Factory::CreateStaticPlane( void )
{
	Mix::Tool::Win32::Dynamics::Impl::StaticPlane* pStaticPlane = new Mix::Tool::Win32::Dynamics::Impl::StaticPlane();

	if( pStaticPlane != NULL )
	{
		if( pStaticPlane->Initialize() == false )
		{
			MIX_DELETE( pStaticPlane );
		}
	}

	return pStaticPlane;
}

Mix::Tool::Win32::Dynamics::StaticMesh* Factory::CreateStaticMesh( void )
{
	return new Mix::Tool::Win32::Dynamics::Impl::StaticMesh();
}

Mix::Tool::Win32::Dynamics::BoxShape* Factory::CreateBoxShape( const D3DXVECTOR3& halfExtents )
{
	Mix::Tool::Win32::Dynamics::Impl::BoxShape* pBoxShape = new Mix::Tool::Win32::Dynamics::Impl::BoxShape();

	if( pBoxShape != NULL )
	{
		if( pBoxShape->Initialize( halfExtents ) == false )
		{
			MIX_DELETE( pBoxShape );
		}
	}

	return pBoxShape;
}

Mix::Tool::Win32::Dynamics::CapsuleShape* Factory::CreateCapsuleShape( Mix::Tool::Win32::Dynamics::AXIS axis, float radius, float length )
{
	Mix::Tool::Win32::Dynamics::Impl::CapsuleShape* pCapsuleShape = new Mix::Tool::Win32::Dynamics::Impl::CapsuleShape();

	if( pCapsuleShape != NULL )
	{
		if( pCapsuleShape->Initialize( axis, radius, length ) == false )
		{
			MIX_DELETE( pCapsuleShape );
		}
	}

	return pCapsuleShape;
}

Mix::Tool::Win32::Dynamics::CapsuleShape* Factory::CreateCapsuleShape( const D3DXVECTOR3& halfExtents )
{
	Mix::Tool::Win32::Dynamics::Impl::CapsuleShape* pCapsuleShape = new Mix::Tool::Win32::Dynamics::Impl::CapsuleShape();

	if( pCapsuleShape != NULL )
	{
		Mix::Tool::Win32::Dynamics::AXIS axis;
		float length;
		float radius;

		Mix::Tool::Win32::Dynamics::CapsuleShape::GetParam( halfExtents, axis, length, radius );

		if( pCapsuleShape->Initialize( axis, radius, length ) == false )
		{
			MIX_DELETE( pCapsuleShape );
		}
	}

	return pCapsuleShape;
}

Mix::Tool::Win32::Dynamics::SphereShape* Factory::CreateSphereShape( float radius )
{
	Mix::Tool::Win32::Dynamics::Impl::SphereShape* pSphereShape = new Mix::Tool::Win32::Dynamics::Impl::SphereShape();

	if( pSphereShape != NULL )
	{
		if( pSphereShape->Initialize( radius ) == false )
		{
			MIX_DELETE( pSphereShape );
		}
	}

	return pSphereShape;
}

Mix::Tool::Win32::Dynamics::SphereShape* Factory::CreateSphereShape( const D3DXVECTOR3& halfExtents )
{
	Mix::Tool::Win32::Dynamics::Impl::SphereShape* pSphereShape = new Mix::Tool::Win32::Dynamics::Impl::SphereShape();

	if( pSphereShape != NULL )
	{
		float radius;

		Mix::Tool::Win32::Dynamics::SphereShape::GetParam( halfExtents, radius );

		if( pSphereShape->Initialize( radius ) == false )
		{
			MIX_DELETE( pSphereShape );
		}
	}

	return pSphereShape;
}

Mix::Tool::Win32::Dynamics::CompoundShape* Factory::CreateCompoundShape( void )
{
	Mix::Tool::Win32::Dynamics::Impl::CompoundShape* pCompoundShape = new Mix::Tool::Win32::Dynamics::Impl::CompoundShape();

	if( pCompoundShape != NULL )
	{
		if( pCompoundShape->Initialize() == false )
		{
			MIX_DELETE( pCompoundShape );
		}
	}

	return pCompoundShape;
}

Mix::Tool::Win32::Dynamics::PointJoint* Factory::CreatePointJoint( void )
{
	return new Mix::Tool::Win32::Dynamics::Impl::PointJoint();
}

Mix::Tool::Win32::Dynamics::PointJoint* Factory::CreatePointJoint( bool collisionDisabled, float spring, float damper )
{
	return new Mix::Tool::Win32::Dynamics::Impl::PointJoint( collisionDisabled, spring, damper );
}

Mix::Tool::Win32::Dynamics::HingeJoint* Factory::CreateHingeJoint( void )
{
	return new Mix::Tool::Win32::Dynamics::Impl::HingeJoint();
}

Mix::Tool::Win32::Dynamics::HingeJoint* Factory::CreateHingeJoint( const D3DXVECTOR3& axis, float lowerLimit, float upperLimit, bool collisionDisabled, float limitSpring, float limitDamper )
{
	return new Mix::Tool::Win32::Dynamics::Impl::HingeJoint( axis, lowerLimit, upperLimit, collisionDisabled, limitSpring, limitDamper );
}

Mix::Tool::Win32::Dynamics::BallJoint* Factory::CreateBallJoint( void )
{
	return new Mix::Tool::Win32::Dynamics::Impl::BallJoint();
}

Mix::Tool::Win32::Dynamics::BallJoint* Factory::CreateBallJoint( const D3DXVECTOR3& swingAxis, const D3DXVECTOR3& twistAxis, float swingLimit1, float swingLimit2, float twistLimit, bool collisionDisabled, float spring, float damper, float limitSpring, float limitDamper )
{
	return new Mix::Tool::Win32::Dynamics::Impl::BallJoint( swingAxis, twistAxis, swingLimit1, swingLimit2, twistLimit, collisionDisabled, spring, damper, limitSpring, limitDamper );
}

Mix::Tool::Win32::Dynamics::RigidBody* Factory::CreateRigidBody( void )
{
	Mix::Tool::Win32::Dynamics::Impl::RigidBody* pRigidBody = new Mix::Tool::Win32::Dynamics::Impl::RigidBody();

	if( pRigidBody != NULL )
	{
		if( pRigidBody->Initialize() == false )
		{
			MIX_DELETE( pRigidBody );
		}
	}

	return pRigidBody;
}

Mix::Tool::Win32::Dynamics::KinematicCharacter* Factory::CreateKinematicCharacter( void )
{
	Mix::Tool::Win32::Dynamics::Impl::KinematicCharacter* pKinematicCharacter = new Mix::Tool::Win32::Dynamics::Impl::KinematicCharacter();

	if( pKinematicCharacter != NULL )
	{
		if( pKinematicCharacter->Initialize() == false )
		{
			MIX_DELETE( pKinematicCharacter );
		}
	}

	return pKinematicCharacter;
}

Mix::Tool::Win32::Dynamics::Design::Actor* Factory::CreateActor( void )
{
	return new Mix::Tool::Win32::Dynamics::Design::Actor();
}

Mix::Tool::Win32::Dynamics::Design::Terrain* Factory::CreateTerrain( void )
{
	return new Mix::Tool::Win32::Dynamics::Design::Terrain();
}

}}}}
