/*
	Welcome back!
	This is one of the shortest source files used in rectangle battle
	and propably one of the most important, for without it not a single
	object on screen would know anything about all the other ones.
	Every class that cares enough about its environment to desire some
	interaction with it must inherit from collision_obj and call one or
	two of the collision_mgr::register_* functions to tell the collision_mgr
	about their existance. Once they cease to roam this virtual world
	they should call the unregister_* functions to make their loss known.
	This is best done in constructor and destructor, as seen in rectangle,
	missile, asteroid and triangle, so basically in every single one of them ;-).
	If their public property dead is true, no one cares about them, which
	is rather cruel, however we are on a battlefield and have not time to
	cry for every single casuality, however sad this might seem.
	The collision_mgr::update() function simply checks every missile for
	collision with every target and calls the hit method of both of them
	if they actually overlap. This is no real accurate collision, just a
	boxed one, yet its enough for this game.
	All of this, of course, could not possibly work without the mighty
	concept that is polymorphism. If you happen to love polymorphism as much
	as i do and happen to be the very first one of your kind to discover
	it, you may use the following co... well, you should know by now:
	KM7K7-4CT76-HJWT4-B47XD-4VP66
	
	I suggest you continue with include/rectangle.h, which contains the
	definition for (surprise) rectangle, implementing this interface.
*/
namespace rectangle_battle
{
	namespace collision_mgr
	{
		class collision_obj
		{
			friend void rectangle_battle::collision_mgr::update();
			protected:
			kos_gfx::math::vector2d<> position, velocity;
			double w,h;
			
			double dmg;
			bool dying;
			
			public:
			bool dead;
			
			virtual ~collision_obj()
			{};
			
			double damage() const
			{
				return dmg;
			};
			
			kos_gfx::math::vector2d<> pos() const
			{
				return position;
			};
			
			kos_gfx::math::vector2d<> vel() const
			{
				return velocity;
			};
			
			kos_gfx::math::vector2d<> center() const
			{
				return kos_gfx::math::vector2d<>(position.x+w/2,position.y+h/2);
			};
			
			virtual void hit(collision_obj *other)=0;
			
			bool collides(collision_obj *other)
			{
				if(dead || other->dead || dying || other->dying)
					return false;
					
				if(position.x+w<other->position.x || position.x>other->position.x+other->w || position.y+h<other->position.y || position.y>other->position.y+other->h)
					return false;
				return true;
			};
			
		};
		
		typedef std::list<collision_obj*>::iterator element;
		
		std::list<collision_obj*> targets;
		std::list<collision_obj*> missiles;
		
		element register_target(collision_obj *obj)
		{
			targets.push_back(obj);
			return --targets.end();
		};
		
		element register_missile(collision_obj *obj)
		{
			missiles.push_back(obj);
			return --missiles.end();
		};
		
		void unregister_target(element elem)
		{
			targets.erase(elem);
		};
		
		void unregister_missile(element elem)
		{
			missiles.erase(elem);
		};
		
		void update()
		{
			for(element it=missiles.begin();it!=missiles.end();++it)
			{
				for(element tar_it=targets.begin();tar_it!=targets.end();++tar_it)
				{
					if((*it)!=(*tar_it) && (*it)->collides(*tar_it))
					{
						(*it)->hit((*tar_it));
						(*tar_it)->hit((*it));
					};
				};
			};
		};
	};
};
