#pragma once

#include "Mix/Dynamics/IObjectDragger.h"
#include "Mix/Dynamics/IObjectListener.h"

namespace Mix{ namespace Dynamics{

	class PointJoint;

	class ObjectDragger : public Mix::Dynamics::IObjectDragger
	{
	private:
		class Context : public Mix::Dynamics::IObjectListener
		{
		private:
			Mix::Dynamics::IWorld* m_pWorld;
			Mix::Dynamics::PointJoint* m_pJoint;
			Mix::Dynamics::IRigidBody* m_pObject;
			Float32 m_Dist;

		public:
			Context( Mix::Dynamics::IWorld* pWorld );
			virtual ~Context( void );

			Boolean CatchStart(	const Mix::Vector3& eyePos,
								const Mix::Vector3& rayFrom,
								const Mix::Vector3& rayTo, 
								UInt16 filter );

			void CatchContinue( const Mix::Vector3& eyePos, const Mix::Vector3& rayTo );

			void Free( void );

			Mix::Dynamics::IWorld* GetWorldPtr( void );
			Mix::Dynamics::IObject* GetObjectPtr( void );

		public:
			virtual void OnAddedToWorld( Mix::Dynamics::IObject* pObject, Mix::Dynamics::IWorld* pWorld );
			virtual void OnRemovedFromWorld( Mix::Dynamics::IObject* pObject, Mix::Dynamics::IWorld* pWorld );
			virtual void OnContact( Mix::Dynamics::IObject* pObject, const Mix::Dynamics::MANIFOLD& manifold );
		};

	private:
		UInt16 m_CatchFilter;
		ObjectDragger::Context* m_pContext;

	public:
		static ObjectDragger* CreateInstance( Mix::Dynamics::IWorld* pWorld );

	protected:
		ObjectDragger( Mix::Dynamics::IWorld* pWorld );
		virtual ~ObjectDragger( void );

	public:
		virtual void GetWorld( Mix::Dynamics::IWorld** ppWorld );

		virtual UInt16 GetCatchFilter( void ) const;
		virtual void SetCatchFilter( UInt16 filter );

		virtual Boolean IsCatch( void ) const;
		virtual Boolean GetCatchObject( Mix::Dynamics::IObject** ppObject );

		virtual Boolean CatchStart( const Mix::Vector3& eyePos, const Mix::Vector3& rayFrom, const Mix::Vector3& rayTo );
		virtual void CatchContinue( const Mix::Vector3& eyePos, const Mix::Vector3& rayTo );
		virtual void Free( void );
	};

}}
