#pragma once

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

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{
	class RigidBody;
}}}}

namespace Mix{ namespace Tool{ namespace Dynamics{

	ref class PhysicsMaterial;
	ref class Shape;

	public enum class RigidBodyStatus
	{
		Default,
		Static,
		Kinematic,
		Sensor,
	};

	public ref class RigidBodyChild
	{
	internal:
		Mix::Tool::Win32::Dynamics::RigidBody* implRigidBody;
		HANDLE implShapeHandle;

		Mix::Tool::Dynamics::Shape^ m_Shape;

	internal:
		RigidBodyChild( Mix::Tool::Win32::Dynamics::RigidBody* _implRigidBody, HANDLE _implShapeHandle, Mix::Tool::Dynamics::Shape^ _shape );
		~RigidBodyChild( void );

	public:
		property Mix::Tool::Dynamics::Shape^ Shape
		{
			Mix::Tool::Dynamics::Shape^ get( void );
			void set( Mix::Tool::Dynamics::Shape^ value );
		}

		property Mix::Tool::Math::Quaternion^ Rotation
		{
			Mix::Tool::Math::Quaternion^ get( void );
			void set( Mix::Tool::Math::Quaternion^ value );
		}

		property Mix::Tool::Math::Vector^ Position
		{
			Mix::Tool::Math::Vector^ get( void );
			void set( Mix::Tool::Math::Vector^ value );
		}
	};

	public ref class RigidBodyChildCollection : System::Collections::IEnumerable
	{
	private:
		Mix::Tool::Win32::Dynamics::RigidBody* impl;
		System::Collections::Generic::List<Mix::Tool::Dynamics::RigidBodyChild^>^ m_List;

	internal:
		RigidBodyChildCollection( Mix::Tool::Win32::Dynamics::RigidBody* impl );
		~RigidBodyChildCollection( void );

	public:
		property int Count
		{
			int get( void );
		}

		property Mix::Tool::Dynamics::RigidBodyChild^ default[int]
		{
			Mix::Tool::Dynamics::RigidBodyChild^ get( int index );
		}

		void Clear( void );

		Mix::Tool::Dynamics::RigidBodyChild^ Add( Mix::Tool::Dynamics::Shape^ shape, Mix::Tool::Math::Quaternion^ rot, Mix::Tool::Math::Vector^ pos );
		bool Remove( Mix::Tool::Dynamics::RigidBodyChild^ child );

		bool Contains( Mix::Tool::Dynamics::RigidBodyChild^ child );

	public:
		virtual System::Collections::IEnumerator^ GetEnumerator( void );
	};

	public ref class RigidBody : public Mix::Tool::Dynamics::CollisionObject
	{
	private:
		Mix::Tool::Win32::Dynamics::RigidBody* impl;
		bool m_bInternalImpl;

		Mix::Tool::Dynamics::RigidBodyChildCollection^ m_Childs;
		Mix::Tool::Dynamics::PhysicsMaterial^ m_PhysicsMaterial;

	internal:
		RigidBody( Mix::Tool::Win32::Dynamics::RigidBody* _impl );

	public:
		RigidBody( void );
		~RigidBody( void );

		property Mix::Tool::Dynamics::RigidBodyChildCollection^ Childs
		{
			Mix::Tool::Dynamics::RigidBodyChildCollection^ get( void );
		}

		property Mix::Tool::Dynamics::PhysicsMaterial^ PhysicsMaterial
		{
			Mix::Tool::Dynamics::PhysicsMaterial^ get( void );
			void set( Mix::Tool::Dynamics::PhysicsMaterial^ value );
		}

		property Mix::Tool::Dynamics::RigidBodyStatus Status
		{
			Mix::Tool::Dynamics::RigidBodyStatus get( void );
			void set( Mix::Tool::Dynamics::RigidBodyStatus value );
		}

		property float Mass
		{
			float get( void );
			void set( float value );
		}

		property float LinearDamping
		{
			float get( void );
			void set( float value );
		}

		property float AngularDamping
		{
			float get( void );
			void set( float value );
		}

		property bool AlwaysActive
		{
			bool get( void );
			void set( bool value );
		}

	internal:
		property Mix::Tool::Win32::Dynamics::CollisionObject* Impl
		{
			virtual Mix::Tool::Win32::Dynamics::CollisionObject* get( void ) override;
		}

	private:
		void PhysicsMaterial_ValueChanged( System::Object^ sender, System::EventArgs^ e );
	};

}}}
