#pragma once

#include "Mix/Reference.h"

namespace Mix{ namespace Scene{ namespace Common{

	class ActorRevision;
	class ActorKinematicCharacter;
	class ActorCollider;
	class ActorSensor;

	class ActorDynamicsCluster : public Mix::Reference
	{
	private:
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::Common::ActorSensor*> SensorList;
		typedef Mix::STL::Map<Mix::Memory::SECTION_SCENE, Mix::StringW, ActorDynamicsCluster::SensorList> SensorListMap;

	protected:
		Mix::Matrix4x4* m_pParentWorldMat;
		Mix::Matrix4x4* m_pWorldMat;

		Mix::Scene::Common::ActorRevision* m_pRevision;

		Mix::Dynamics::IWorld* m_pWorld;

		Mix::Scene::DYNAMICS_COLLIDER_MODE m_ColliderMode;
		Mix::Scene::Common::ActorCollider* m_pCollider;

		Boolean m_bSensorEnabled;
		ActorDynamicsCluster::SensorListMap m_SensorListMap;
		ActorDynamicsCluster::SensorList m_SensorList;

	protected:
		ActorDynamicsCluster( void );
		virtual ~ActorDynamicsCluster( void );

		Boolean Clone( ActorDynamicsCluster* pCloneCluster );

	public:
		void SetCollider( Mix::Scene::Common::ActorCollider* pCollider );
		Mix::Scene::Common::ActorCollider* GetColliderPtr( void ) const;

		void AddSensor( Mix::Scene::Common::ActorSensor* pSensor );
		void FinishSensors( UIntT num );
		UInt32 GetSensorCount( void ) const;
		Mix::Scene::Common::ActorSensor* GetSensorPtr( UInt32 index ) const;

	protected:
		virtual void OnColliderStateChanged( Boolean state ) {}
		virtual void OnColliderModeChanged( Mix::Scene::DYNAMICS_COLLIDER_MODE mode ) {}
		virtual void OnSensorStateChanged( Boolean state ) {}

	public:
		//リンク
		virtual void SetLink( Mix::Scene::IRendererObject* pOwner, Mix::Matrix4x4* pParentWorldMat, Mix::Matrix4x4* pWorldMat );

		//コライダー
		Boolean IsColliderEnabled( void ) const;
		void SetColliderEnabled( Boolean state );
		Mix::Scene::DYNAMICS_COLLIDER_MODE GetColliderMode( void ) const;
		void SetColliderMode( Mix::Scene::DYNAMICS_COLLIDER_MODE mode );
		Mix::Matrix4x4 GetColliderMatrix( void ) const;

		//センサー
		Boolean IsSensorEnabled( void ) const;
		void SetSensorEnabled( Boolean state );

		//衝突するクラスターかどうかの確認( コライダー、もしくわキネマティックキャラクターを所持 )
		virtual Boolean IsCollide( void ) const;
		//ワールドトランスフォームをクラスター側で更新しているかどうかの確認( 非活動状態でも True を返します )
		virtual Boolean IsControl( void ) const;
		//活動状態かどうかの確認
		virtual Boolean IsActive( void ) const;

		//ワールド
		virtual void AttachToWorld( Mix::Dynamics::IWorld* pWorld, Mix::Dynamics::IObjectListener* pObjectListener );
		virtual void DetachFromWorld( Mix::Dynamics::IWorld* pWorld );

		//リセット( 強制 )
		virtual void Reset( void );
		virtual void ResetChild( const Mix::Matrix4x4& baseMat ); //上のリセットから呼び出される

		//アップデート( ワールドのシミュレーション前のワールド行列の更新後に呼ぶ )
		virtual void Update( void );
		virtual Boolean NeedsUpdateChild( void ) const;
		virtual void UpdateChild( const Mix::Matrix4x4& baseMat ); //上の Update から呼び出される

		//リフレッシュ( ワールドのシミュレーション後に呼ぶ )
		//返値 : ワールドトランスフォームを更新した場合は True を返します
		virtual Boolean Refresh( void );

		//破棄
		virtual void Dispose( void );

#ifdef _DEBUG
		virtual void Debug_Draw(	UInt32 flags,
									Mix::Graphics::Utility::IPerspectiveRenderer* pPerspectiveRenderer,
									Float32 axisScaling,
									Float32 jointFrameMinSize,
									Float32 jointLimitScaling );
#endif //_DEBUG
	};

}}}
