#pragma once

#include <list>

namespace Mix{ namespace Scene{ namespace Common{

	class DynamicsObject
	{
	public:
		struct OBJECT_WRAPPER
		{
			Mix::Scene::IDynamicsObject* pObject;
			Mix::Scene::Common::DynamicsObject* pInternalObject;
		};

	private:
		typedef std::list<Mix::Scene::IContactListener*> ContactListenerList;

	private:
		Boolean m_bEnabled;
		Mix::Dynamics::IObjectListener* m_pObjectListener;
		DynamicsObject::ContactListenerList m_ContactListenerList;
		Int32 m_UserIndex;
		void* m_UserPtr;

		DynamicsObject::OBJECT_WRAPPER m_ObjectWrapper;

	protected:
		Mix::Dynamics::IWorld* m_pWorld;

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

		void Initialize( Mix::Scene::IDynamicsObject* pObject );

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

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

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

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

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

		void Attach( Mix::Dynamics::IWorld* pWorld, Mix::Dynamics::IObjectListener* pObjectListener );
		void Detach( Mix::Dynamics::IWorld* pWorld );

		void NotifyContact( Mix::Scene::IDynamicsObject* pObjectA,
							Mix::Scene::IDynamicsObject* pObjectB,
							UInt32 pointCount,
							const Mix::Scene::DYNAMICS_CONTACT_POINT* points );
	};

}}}
