#pragma once

using namespace System;
using namespace System::ComponentModel;

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

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{
	class Shape;
	class BoxShape;
	class CapsuleShape;
	class SphereShape;
}}}}

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{ namespace Design{
	class Basic;
}}}}}

namespace Mix{ namespace Tool{ namespace Dynamics{
	ref class Shape;
	ref class PhysicsMaterial;
}}}

namespace Mix{ namespace Tool{ namespace Dynamics{ namespace Design{

	ref class BoundingBox;

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Shape
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class Shape
	{
	protected:
		Mix::Tool::Win32::Dynamics::Design::Basic* implBasic;
		HANDLE hObject;
		HANDLE hShape;

		Mix::Tool::Dynamics::Design::BoundingBox^ m_BoundingBox;
		Mix::Tool::Math::Vector^ m_Rot;
		Mix::Tool::Math::Vector^ m_Pos;

	public:
		Shape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox );
		Shape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox, Mix::Tool::Math::Vector^ _rot, Mix::Tool::Math::Vector^ _pos );
		virtual ~Shape( void );

	protected:
		[Browsable(false)]
		property Mix::Tool::Win32::Dynamics::Shape* Win32Shape
		{
			void set( Mix::Tool::Win32::Dynamics::Shape* value );
		}

	internal:
		property HANDLE Win32Handle
		{
			HANDLE get( void );
		}

		virtual void OnAdded( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject );
		virtual void OnRemoved( void );

	public:
		[Browsable(false)]
		property Mix::Tool::Dynamics::Design::BoundingBox^ BoundingBox
		{
			Mix::Tool::Dynamics::Design::BoundingBox^ get( void );
			void set( Mix::Tool::Dynamics::Design::BoundingBox^ value );
		}

		[Browsable(false)]
		property Mix::Tool::Math::Vector^ Rotation
		{
			Mix::Tool::Math::Vector^ get( void );
			void set( Mix::Tool::Math::Vector^ value );
		}

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

		virtual void Reset( void );

		void ResetRotation( void );
		void ResetPosition( void );
	};

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// BoxShape
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class BoxShape : public Mix::Tool::Dynamics::Design::Shape
	{
	private:
		Mix::Tool::Win32::Dynamics::BoxShape* m_pShape;

	public:
		BoxShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox );
		BoxShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox, Mix::Tool::Math::Vector^ _halfExtents, Mix::Tool::Math::Vector^ _rot, Mix::Tool::Math::Vector^ _pos );
		virtual ~BoxShape( void );

		[Category("\t\t基本")]
		[Description( L"ＸＹＺ軸の半分の長さを指定します。" )]
		[TypeConverter(Mix::Tool::Math::VectorConverter::typeid)]
		property Mix::Tool::Math::Vector^ HalfExtents
		{
			Mix::Tool::Math::Vector^ get( void );
			void set( Mix::Tool::Math::Vector^ value );
		}

	private:
		void NewShape( Mix::Tool::Math::Vector^ he );

	public:
		virtual void Reset( void ) override;

	internal:
		virtual void OnAdded( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject ) override;
		virtual void OnRemoved( void ) override;
	};

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// CapsuleShape
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class CapsuleShape : public Mix::Tool::Dynamics::Design::Shape
	{
	private:
		Mix::Tool::Win32::Dynamics::CapsuleShape* m_pShape;

	public:
		CapsuleShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox );
		CapsuleShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox, Mix::Tool::Dynamics::Axis _axis, float _length, float _radius, Mix::Tool::Math::Vector^ _rot, Mix::Tool::Math::Vector^ _pos );
		virtual ~CapsuleShape( void );

		[Description( L"軸を指定します。" )]
		property Mix::Tool::Dynamics::Axis Axis
		{
			Mix::Tool::Dynamics::Axis get( void );
			void set( Mix::Tool::Dynamics::Axis value );
		}

		[Description( L"長さを指定します。" )]
		property float Length
		{
			float get( void );
			void set( float value );
		}

		[Description( L"半径を指定します。" )]
		property float Radius
		{
			float get( void );
			void set( float value );
		}

	private:
		void NewShape( Mix::Tool::Math::Vector^ he );
		void NewShape( Mix::Tool::Dynamics::Axis axis, float length, float radius );
		void NewShape( Mix::Tool::Win32::Dynamics::CapsuleShape* pShape );

		static Mix::Tool::Win32::Dynamics::AXIS ToW32Axis( Mix::Tool::Dynamics::Axis axis );
		static Mix::Tool::Dynamics::Axis ToCLRAxis( Mix::Tool::Win32::Dynamics::AXIS axis );

	public:
		virtual void Reset( void ) override;

	internal:
		virtual void OnAdded( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject ) override;
		virtual void OnRemoved( void ) override;
	};

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// SphereShape
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class SphereShape : public Mix::Tool::Dynamics::Design::Shape
	{
	private:
		Mix::Tool::Win32::Dynamics::SphereShape* m_pShape;

	public:
		SphereShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox );
		SphereShape( Mix::Tool::Dynamics::Design::BoundingBox^ _boundingBox, float _radius, Mix::Tool::Math::Vector^ _rot, Mix::Tool::Math::Vector^ _pos );
		virtual ~SphereShape( void );

		[Description( L"半径を指定します。" )]
		property float Radius
		{
			float get( void );
			void set( float value );
		}

	private:
		void NewShape( Mix::Tool::Math::Vector^ he );
		void NewShape( float radius );
		void NewShape( Mix::Tool::Win32::Dynamics::SphereShape* pNewShape );

	public:
		virtual void Reset( void ) override;

	internal:
		virtual void OnAdded( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject ) override;
		virtual void OnRemoved( void ) override;
	};

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// ShapeCollection
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class ShapeCollection : public System::Collections::IEnumerable
	{
	private:
		Mix::Tool::Win32::Dynamics::Design::Basic* implBasic;
		HANDLE hObject;

		System::Collections::Generic::List<Mix::Tool::Dynamics::Design::Shape^>^ m_List;
		Mix::Tool::Dynamics::Design::Shape^ m_Selected;

	internal:
		ShapeCollection( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject );
		~ShapeCollection( void );

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

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

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

		bool Add( Mix::Tool::Dynamics::Design::Shape^ shape );
		bool Remove( Mix::Tool::Dynamics::Design::Shape^ shape );

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

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// BasicChild
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public enum class BasicChildType
	{
		Collider,
		Sensor,
	};

	public enum class BasicChildStatus
	{
		Default,
		Static,
		Kinematic
	};

	[Flags]
	public enum class RotationAxisFlags
	{
		None	= 0x00000000,
		X		= 0x00000001,
		Y		= 0x00000002,
		Z		= 0x00000004,
		All		= 0x00000007,
	};

	public ref class BasicChild
	{
	public:
		event System::EventHandler^ NameChanged;

	private:
		Mix::Tool::Win32::Dynamics::Design::Basic* implBasic;
		HANDLE hObject;

		Mix::Tool::Dynamics::Design::ShapeCollection^ m_Shapes;
		Mix::Tool::Dynamics::PhysicsMaterial^ m_PhysicsMaterial;

	internal:
		BasicChild( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic, HANDLE _hObject );
		~BasicChild( void );

		property HANDLE Win32Handle
		{
			HANDLE get( void );
		}

	public:
		/*
			共通
		*/

		property BasicChildType Type
		{
			BasicChildType get( void );
		}

		property System::String^ Name
		{
			System::String^ get( void );
			void set( System::String^ value );
		}

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

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

		void ResetCenterRotation( void );
		void ResetCenterPosition( void );

		property Mix::Tool::Dynamics::Design::ShapeCollection^ Shapes
		{
			Mix::Tool::Dynamics::Design::ShapeCollection^ get( void );
		}

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

		/*
			コライダー
		*/

		property BasicChildStatus Status
		{
			BasicChildStatus get( void );
			void set( BasicChildStatus value );
		}

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

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

		property Mix::Tool::Dynamics::Design::RotationAxisFlags RotationAxisFlags
		{
			Mix::Tool::Dynamics::Design::RotationAxisFlags get( void );
			void set( Mix::Tool::Dynamics::Design::RotationAxisFlags value );
		}

		/*
			センサー
		*/

		//特に無し

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

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// BasicChildCollection
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class BasicChildCollection : public System::Collections::IEnumerable
	{
	private:
		Mix::Tool::Win32::Dynamics::Design::Basic* implBasic;
		System::Collections::Generic::List<Mix::Tool::Dynamics::Design::BasicChild^>^ m_List;
		Mix::Tool::Dynamics::Design::BasicChild^ m_Selected;

	internal:
		BasicChildCollection( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic );
		~BasicChildCollection( void );

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

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

		property Mix::Tool::Dynamics::Design::BasicChild^ Selected
		{
			Mix::Tool::Dynamics::Design::BasicChild^ get( void );
			void set( Mix::Tool::Dynamics::Design::BasicChild^ value );
		}

		bool Addable( Mix::Tool::Dynamics::Design::BasicChildType type );

		Mix::Tool::Dynamics::Design::BasicChild^ Add( Mix::Tool::Dynamics::Design::BasicChildType type );
		void Remove( Mix::Tool::Dynamics::Design::BasicChild^ child );

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

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Basic
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public ref class Basic
	{
	private:
		BasicChildCollection^ m_Childs;

	internal:
		Basic( Mix::Tool::Win32::Dynamics::Design::Basic* _implBasic );
		virtual ~Basic( void );

	public:
		property Mix::Tool::Dynamics::Design::BasicChildCollection^ Childs
		{
			Mix::Tool::Dynamics::Design::BasicChildCollection^ get( void );
		}
	};

}}}}
