#pragma once

#include <list>
#include "Mix/Dynamics/IObjectListener.h"

class Room
{
public:
	enum GROUP
	{
		GROUP_CAMERA			= 0x0001,
		GROUP_FLOOR				= 0x0002,
		GROUP_OBJECT			= 0x0004,
		GROUP_PICK				= 0x0008,
		GROUP_EXPLOSION			= 0x0010,

		GROUP_CAMERA_MASK		= ( GROUP_FLOOR | GROUP_OBJECT ),
		GROUP_FLOOR_MASK		= ( GROUP_CAMERA | GROUP_OBJECT ),
		GROUP_OBJECT_MASK		= ( GROUP_CAMERA | GROUP_FLOOR | GROUP_OBJECT | GROUP_PICK | GROUP_EXPLOSION ),
		GROUP_PICK_MASK			= ( GROUP_OBJECT ),
		GROUP_EXPLOSION_MASK	= ( GROUP_OBJECT ),
	};

private:
	class Exploser : public Mix::Dynamics::IObjectListener
	{
	public:
		static Exploser* CreateInstance( void );

	private:
		Boolean m_bApply;
		Float32 m_ApplyImpulse;

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

	public:
		void Apply( Float32 impulse );
		void Refresh( 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 );
	};

	typedef std::list<Mix::Dynamics::IRigidBody*> RigidBodyList;

private:
	Mix::Dynamics::IManager* m_pDynamicsMgr;
	Mix::Dynamics::IWorld* m_pWorld;

	Mix::Dynamics::IPointJoint* m_pPick;
	Mix::Dynamics::IRigidBody* m_pPickRigidBody;
	Float32 m_PrePickDist;

	Mix::Dynamics::ISensor* m_pExplosionSensor;
	Room::Exploser* m_pExploser;

	Float32 m_Abyss;

	Room::RigidBodyList m_RigidBodyList;

public:
	Room( void );
	~Room( void );

public:
	Boolean Initialize( Mix::Dynamics::IManager* pDynamicsMgr,
						Mix::Dynamics::IWorld* pWorld,
						Float32 abyss = -50.0f );

	void Clear();

	Mix::Dynamics::IRigidBody* AddBox( const Mix::Vector3& scale, const Mix::Vector3& pos );
	Mix::Dynamics::IRigidBody* AddSphere( Float32 radius, const Mix::Vector3& pos );

	UInt32 GetObjectCount( void ) const;

	void MousePressed( const Mix::Vector3& eyePos, const Mix::Matrix4x4& viewMat, const Mix::Matrix4x4& projMat, const Mix::Vector2& mousePos, const Mix::Vector2& screenSize );
	void MouseDown( const Mix::Vector3& eyePos, const Mix::Matrix4x4& viewMat, const Mix::Matrix4x4& projMat, const Mix::Vector2& mousePos, const Mix::Vector2& screenSize );
	void MouseReleased( void );

	void Explosion( const Mix::Vector3& pos, Float32 impulse );

	void Refresh( void );
	void Dispose( void );

private:
	static const Float32 EXPLOSION_RADIUS;
};
