/*
	Hi,
	as can be guessed from the games name, you are about to learn about
	the class everything is based on. Without a rectangle, no rectangle
	battle could exist ;-). There might be a little more to explain here,
	so i will split it into parts and begin with update(), jump to line
	220 now;
*/
namespace rectangle_battle
{
	class rectangle:public rectangle_battle::collision_mgr::collision_obj
	{
		private:
		kos_gfx::math::vector2d<> start_pos;
		int start_width, start_height;
		
		int inner_w, inner_h;
		
		uint32 color;
		kos_gfx::Uint8 player_id;
		ORIENTATION orient;
		rectangle_battle::collision_mgr::element collision_elem;
		
		std::list<basic_missile*> missiles;
		int number_of_active_missiles, number_of_max_missiles;
		int number_of_special_missiles;
		
		int dead_counter, max_dead_counter;
		
		kos_gfx::sound::sfx::handle missile_sfx, missile_hit_sfx;
		
		kos_gfx::pvr::texture_fragment normal_missile_tex, special_missile_tex;
		
		rectangle_battle::barrier bar;
		
		public:
		static kos_gfx::Uint32 points;
		
		rectangle(int sx, int sy, int sw, int sh, int inner_width, int inner_height, kos_gfx::Uint8 r, kos_gfx::Uint8 g, kos_gfx::Uint8 b, kos_gfx::Uint8 pl_id=0, ORIENTATION ori=UP):
		player_id(pl_id),inner_w(inner_width),inner_h(inner_height),orient(ori)
		{
			points=0;
			
			missile_sfx=0;
			missile_hit_sfx=0;
			max_dead_counter=180;
			
			start_width=sw;
			start_height=sh;
			start_pos=kos_gfx::math::vector2d<>(sx,sy);
			
			color=PVR_PACK_COLOR(1,((double)r)/255,((double)g)/255,((double)b)/255);
			
			collision_elem=rectangle_battle::collision_mgr::register_target(this);
			
			reset();
		};
		
		~rectangle()
		{
			free_missiles();
			rectangle_battle::collision_mgr::unregister_target(collision_elem);
		};
		
		void free_missiles()
		{
			for(std::list<basic_missile*>::iterator it=missiles.begin();it!=missiles.end();++it)
			{
				basic_missile *tmp=(*it);
				it=missiles.erase(it);
				--it;
				delete tmp;
				--number_of_active_missiles;
			};
		};
		
		void reset()
		{
			free_missiles();
			
			number_of_active_missiles=0;
			number_of_max_missiles=3;
			number_of_special_missiles=0;
			dead=false;
			dying=false;
			position=start_pos;
			w=start_width;
			h=start_height;
			bar.destroy();
			
			dead_counter=0;
		};
		
		void set_sounds(kos_gfx::sound::sfx::handle miss,kos_gfx::sound::sfx::handle miss_hit)
		{
			missile_sfx=miss;
			missile_hit_sfx=miss_hit;
		};
		
		void set_missile_textures(kos_gfx::pvr::texture_fragment miss_tex, kos_gfx::pvr::texture_fragment special_miss_tex)
		{
			normal_missile_tex=miss_tex;
			special_missile_tex=special_miss_tex;
			
			bar.create(special_missile_tex,0,0,6,10,orient); //yeah, weird place to put this, however the barrier uses the same image, and this image is assigned here, therefore the barrier must be created in this very method(or i would have to reorganize some parts of the code, and I am a really lazy bastard ;-));
			bar.destroy();
		};
		
		void move_to(double new_x, double new_y)
		{
			position.x=new_x>kos_gfx::pvr::TITLE_SAFE_LEFT?
				(new_x+w>kos_gfx::pvr::TITLE_SAFE_RIGHT?kos_gfx::pvr::TITLE_SAFE_RIGHT-w:new_x)
				:kos_gfx::pvr::TITLE_SAFE_LEFT;
			position.y=new_y>kos_gfx::pvr::TITLE_SAFE_TOP?
				(new_y+h>kos_gfx::pvr::TITLE_SAFE_BOTTOM?kos_gfx::pvr::TITLE_SAFE_BOTTOM-h:new_y)
				:kos_gfx::pvr::TITLE_SAFE_TOP;
		};
		
		void move(double mx,double my)
		{
			velocity.x=mx;
			velocity.y=my;
			move_to(position.x+mx,position.y+my);
		};
		
		//This is called whenever the player decides to shoot a missile,
		//however it may reject him if he has no missiles left.
		//there is a restriction on how many missiles may exist simultaneously,
		//which is disabled if there are special missiles, however those
		//are limited, too.
		//the missiles are of type basic_missile, which is defined in
		//include/missile.h and are collected in a list (appropriately)
		//called missiles. Their movement and destruction is handled in 
		//update_missiles(), which can be found in line 199.
		void shoot()
		{
			if(number_of_active_missiles<number_of_max_missiles || number_of_special_missiles>0)
			{
				if(missile_sfx!=0)
					kos_gfx::sound::sfx::play(missile_sfx);
					
				if(number_of_special_missiles>0)
				{
					--number_of_special_missiles;
					missiles.push_back(new basic_missile(special_missile_tex,
						position.x+(w/2)-5,position.y+(orient==UP?-20:h+20),10,10,velocity.x/4,velocity.y/4+(orient==UP?-2:2),0.2,2));
				}
				else
				{
					missiles.push_back(new basic_missile(normal_missile_tex,
						position.x+(w/2)-5,position.y+(orient==UP?-20:h+20),10,10,velocity.x/4,velocity.y/4+(orient==UP?-2:2),0.2));
				};
				++number_of_active_missiles;
			};
		};
		
		//well, i said "remotely", didnt i? ;-)
		//It merely removes x pixels from the rectangles size
		//(which is its protective shell ingame) and declares it dead
		//if this shell is broken and the inner part is damaged.
		//Furthermore it has a special case for the items, which
		//are implemented really, really bad, abuse the fact that
		//no other object does negative damage and use this to identify
		//themselfs ;-)
		//well, this is all i have to say about this file, i will continue
		//with basic_missile, found in include/missile.h.
		void hit(collision_obj *other)
		{
			if(missile_hit_sfx!=0)
				kos_gfx::sound::sfx::play(missile_hit_sfx);
				
			//special item case ;-)
			if(other->damage()<0)
			{
				if(other->damage()==rectangle_battle::ATTACK)
				{
					number_of_special_missiles+=10;
					points+=20;
				}
				else
				{
					bar.restore();
					points+=10;
				};
				
				other->hit(NULL); //tell the item it has been collected ;-);
				return;
			};
				
			w-=other->damage();
			h-=other->damage();
			dmg=w;
			if(w<inner_w || h<inner_h)
			{
				dead=true;
			};
		};
		
		//This simply iterates over all missiles, deletes them if they
		//are dead and calls update on them otherwise.
		//There is but one more thing in this file that i consider even
		//remotely interesting, which is the hit() method in line 157.
		void update_missiles()
		{
			for(std::list<basic_missile*>::iterator it=missiles.begin();it!=missiles.end();++it)
			{
				if((*it)->dead)
				{
					basic_missile *tmp=(*it);
					it=missiles.erase(it);
					--it;
					delete tmp;
					--number_of_active_missiles;
				}
				else
					(*it)->update();
			};
		};
		
		//this method takes care of handling player input and of increasing
		//the counter for the dying animation(the cheap explosion effect ;-));
		//Furthermore it calls the method which handles missiles and updates
		//the barrier. Movement is handled via the simple method move, 
		//which simply calls move_to, which sets the new position after
		//checking its legality.
		//shooting is a little more complex, so i suggest you have a look at
		//shoot(), which can be found in line 126;
		void update()
		{
			if(dead)
			{
				if(dead_counter<max_dead_counter)
					++dead_counter;
				return;
			};
			
			move(
			((double)kos_gfx::input::controllers[player_id].joystick_x)/62,
			((double)kos_gfx::input::controllers[player_id].joystick_y)/62
			);
				
			if(kos_gfx::input::controllers[player_id].clicked_buttons&kos_gfx::input::BUTTON_A)
				shoot();
				
			update_missiles();
			
			bar.update(position,velocity,w,h);
		};
		
		void draw_explosion()
		{
			for(int j=1;j<inner_w;++j)
			{
				kos_gfx::math::vector2d<> rot_vec(orient==UP?1:-1,0);
				rot_vec.rotate(2*kos_gfx::math::PI/j);
				double distance=(inner_w*10)*((double)dead_counter/(double)max_dead_counter);
				for(int i=1;i<inner_h/2;++i)
				{
					kos_gfx::pvr::draw_rectangle(position.x-i*distance*rot_vec.x,position.y-i*distance*rot_vec.y,2*w*i/inner_w,2*h*i/inner_h,color);
				};
			};
		};
		
		void draw_missiles()
		{
			for(std::list<basic_missile*>::iterator it=missiles.begin();it!=missiles.end();++it)
			{
				(*it)->draw();
			};
		};
		
		void draw()
		{
			if(dead)
			{
				draw_explosion();
			}
			else
			{
				kos_gfx::pvr::draw_rectangle(position.x,position.y,w,h,PVR_PACK_COLOR(1,110.0f/255,110.0f/255,110.0f/255));
				kos_gfx::pvr::draw_rectangle(position.x+w/2-inner_w/2,position.y+h/2-inner_h/2,inner_w,inner_h,color);
			
				draw_missiles();
				
				bar.draw();
			};
		};
	};
	
	kos_gfx::Uint32 rectangle::points;
};
