#pragma once

#include "Mix/Scene/ISimpleCollider.h"
#include "Mix/Scene/ISimpleSensor.h"
#include "Mix/Private/Scene/Common/Ghost.h"
#include "Mix/Private/Scene/Common/DynamicsObject.h"

namespace Mix{ namespace Scene{ namespace Common{

	class LibertyCollider;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ゴースト : ベイシス
	////////////////////////////////////////////////////////////////////////////////////////////////////

	class BasisGhost : public Mix::Scene::Common::Ghost
	{
	protected:
		virtual ~BasisGhost( void );

	public:
		virtual Mix::Scene::Common::DynamicsObject* GetInternalDynamicsObjectPtr( void ) const = 0;

		virtual void AttachDynamics( Mix::Dynamics::IWorld* pWorld, Mix::Dynamics::IObjectListener* pObjectListener );
		virtual void DetachDynamics( Mix::Dynamics::IWorld* pWorld );

	public:
		/*
			Mix::Scene::IGhost
		*/

		virtual Boolean NeedsRefresh( void ) const;
		virtual void Refresh( void );

	public:
		static const wchar_t* FAILED_CREATE;
	};

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ゴースト : 衝突有り
	////////////////////////////////////////////////////////////////////////////////////////////////////

	class CollideGhost : public Mix::Scene::Common::BasisGhost
	{
	public:
		static CollideGhost* CreateInstance( void );

	private:
		Mix::Scene::Common::LibertyCollider* m_pCollider;

	private:
		CollideGhost( void );
		virtual ~CollideGhost( void );

	public:
		Boolean Initialize( Mix::Dynamics::IShape* pShape, const wchar_t* pDebugName );

	public:
		/*
			Mix::Scene::Common::BasisGhost
		*/

		virtual Mix::Scene::Common::DynamicsObject* GetInternalDynamicsObjectPtr( void ) const;

		/*
			Mix::Scene::Common::Ghost
		*/

		virtual Mix::Dynamics::IObject* GetInternalObjectPtr( void ) const;

		/*
			Mix::Scene::IGhost
		*/

		virtual Boolean GetDynamicsObject( Mix::Scene::IDynamicsObject** ppDynamicsObject );

//		virtual Boolean IsEnabled( void ) const;
//		virtual void SetEnabled( Boolean state );

		virtual Mix::Quaternion GetWorldRotation( void ) const;
		virtual void SetWorldRotation( const Mix::Quaternion& rot );

		virtual Mix::Vector3 GetWorldPosition( void ) const;
		virtual void SetWorldPosition( const Mix::Vector3& pos );

		virtual Mix::Matrix4x4 GetWorldMatrx( void ) const;
		virtual void SetWorldMatrix( const Mix::Matrix4x4& mat );

		/*
			Mix::Scene::IRendererObject
		*/

//		virtual Mix::Scene::IRendererObject::TYPE GetType( void ) const;

//		virtual Int32 GetUserIndex( void )  const;
//		virtual void SetUserIndex( Int32 index );

//		virtual void* GetUserPtr( void ) const;
//		virtual void SetUserPtr( void* pData );
	};

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ゴースト : 衝突無し
	////////////////////////////////////////////////////////////////////////////////////////////////////

	class NoCollideGhost : public Mix::Scene::Common::BasisGhost
	{
	private:
		class InternalSensor : public Mix::Scene::ISimpleSensor, public Mix::Scene::Common::DynamicsObject
		{
		public:
			static InternalSensor* CreateInstance( Mix::Scene::IRendererObject* pOwner, const wchar_t* pDebugName );

		private:
			Mix::Scene::IRendererObject* m_pOwner;
			Mix::StringW m_Name;
			Mix::Dynamics::ISensor* m_pSensor;

		private:
			InternalSensor( Mix::Scene::IRendererObject* pOwner, const wchar_t* pName );
			virtual ~InternalSensor( void );

		public:
			Boolean Initialize( Mix::Dynamics::IShape* pShape );
			void Dispose( void );

		public:
			/*
				Mix::Scene::Common::DynamicsObject
			*/

			virtual Mix::Dynamics::IObject* GetInternalObjectPtr( void ) const;

			/*
				Mix::Scene::ISensor
			*/

			virtual const wchar_t* GetName( void ) const;

			virtual UInt16 GetFilterGroup( void ) const;
			virtual void SetFilterGroup( UInt16 filterGroup );

			virtual UInt16 GetFilterMask( void ) const;
			virtual void SetFilterMask( UInt16 filterMask );

			virtual const Mix::Dynamics::MATERIAL& GetMaterial( void ) const;
			virtual void SetMaterial( const Mix::Dynamics::MATERIAL& material );

			/*
				Mix::Scene::IDynamicsObject
			*/

			virtual Mix::Scene::IDynamicsObject::TYPE GetType( void ) const;

			virtual Boolean GetOwner( Mix::Scene::IRendererObject** ppOwner );
			virtual Mix::Scene::IRendererObject* GetOwnerPtr( void ) const;

			virtual Mix::Matrix4x4 GetWorldMatrix( void ) const;
			virtual Mix::Quaternion GetWorldRotation( void ) const;
			virtual Mix::Vector3 GetWorldPosition( void ) const;

			virtual Boolean HasContactListener( void ) const;
			virtual Boolean ContainsContactListener( Mix::Scene::IContactListener* pListener ) const;
			virtual Boolean AddContactListener( Mix::Scene::IContactListener* pListener );
			virtual Boolean RemoveContactListener( Mix::Scene::IContactListener* pListener );
			virtual void ClearContactListener( void );

			virtual Int32 GetUserIndex( void )  const;
			virtual void SetUserIndex( Int32 index );

			virtual void* GetUserPtr( void ) const;
			virtual void SetUserPtr( void* ptr );

		private:
			static const UInt16 FILTER_GROUP;
			static const UInt16 FILTER_MASK;
		};

	public:
		static NoCollideGhost* CreateInstance( void );

	private:
		NoCollideGhost::InternalSensor* m_pSensor;

	private:
		NoCollideGhost( void );
		virtual ~NoCollideGhost( void );

	public:
		Boolean Initialize( Mix::Dynamics::IShape* pShape, const wchar_t* pDebugName );

	public:
		/*
			Mix::Scene::Common::BasisGhost
		*/

		virtual Mix::Scene::Common::DynamicsObject* GetInternalDynamicsObjectPtr( void ) const;

		/*
			Mix::Scene::Common::Ghost
		*/

		virtual Mix::Dynamics::IObject* GetInternalObjectPtr( void ) const;

		/*
			Mix::Scene::IGhost
		*/

		virtual Boolean GetDynamicsObject( Mix::Scene::IDynamicsObject** ppDynamicsObject );

//		virtual Boolean IsEnabled( void ) const;
//		virtual void SetEnabled( Boolean state );

		virtual Mix::Quaternion GetWorldRotation( void ) const;
		virtual void SetWorldRotation( const Mix::Quaternion& rot );

		virtual Mix::Vector3 GetWorldPosition( void ) const;
		virtual void SetWorldPosition( const Mix::Vector3& pos );

		virtual Mix::Matrix4x4 GetWorldMatrx( void ) const;
		virtual void SetWorldMatrix( const Mix::Matrix4x4& mat );

		/*
			Mix::Scene::IRendererObject
		*/

//		virtual Mix::Scene::IRendererObject::TYPE GetType( void ) const;

//		virtual Int32 GetUserIndex( void )  const;
//		virtual void SetUserIndex( Int32 index );

//		virtual void* GetUserPtr( void ) const;
//		virtual void SetUserPtr( void* pData );
	};

}}}
