package net.phatcode.rel;

/**
 *
 * @author Richard Eric M. Lope (Relminator)
 * @version 1.00 2013/3/04
 */

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import net.phatcode.rel.Entity.RenderMode;
import net.phatcode.rel.math.Vector2D;
import net.phatcode.rel.utils.ImageAtlas;
import net.phatcode.rel.utils.LinkedArray;


public class BulletFactory 
{
	
	private LinkedArray<BulletEntity> bullets;
	
	
	public BulletFactory( int size )
	{
		
		bullets = new LinkedArray<BulletEntity>( size, new BulletEntity() );
		int s = bullets.getSize();
		for( int i = 0; i < s; i++ )
		{
			bullets.set( i, new BulletEntity() );
		}
		
	}
	
	public int getSize()
	{
		return bullets.getSize();
	}
	
	public int getActiveBullets()
	{
		return bullets.getActiveElements();
	}
	
	public BulletEntity getFreeBullet()
	{
		return bullets.getFreeElement();
	}
	
	public BulletEntity getBullet( int index )
	{
		return bullets.get( index );
	}
	public int addBullet( BulletEntity bullet )
	{
		return bullets.add( bullet );
	}
	
	public void removeBullet( int index )
	{
		bullets.remove( index );
	}
	
	public void destroyAllBullets()
	{
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get(i);
			
			if( b.isActive() )
			{
				//b.kill() ;
				b.explode();
				bullets.remove(i);
			}
		}
		
	}
	
	public void killAllBullets()
	{
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get(i);
			
			if( b.isActive() )
			{
				b.kill() ;
				bullets.remove(i);
			}
		}

	}
	
	public void updateBullets( Vector2D playerPosition )
	{
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get(i);
			
			if( b.isActive() )
			{
				b.update( playerPosition );
				if( (b.position.x < -20) || (b.position.x > (Constants.SCREEN_WIDTH + 20)) ||
					(b.position.y < -20) || (b.position.y > (Constants.SCREEN_HEIGHT + 20)) )
				{
					b.kill() ;
					bullets.remove(i);
				}
			}
		}
		
	}
	
	public void collideWithPlayer( ShipEntity viper )
	{
		
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get( i );
			
			if( b.isActive() )
			{
				if( b.collidesWith( viper ) )
				{
					b.kill() ;
					bullets.remove( i );
					viper.setRenderMode( RenderMode.WHITE );
				}
			}
		}
		
	}
	
	public void renderBullets( Screen screen, Graphics2D g, ImageAtlas imageAtlas )
	{
        
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get(i);
			
			if( b.isActive() )
			{
				BufferedImage sprite = imageAtlas.getSprite(b.getFrame());
				g.drawImage( sprite, 
							 (int)b.position.x - sprite.getWidth()/2,
							 (int)b.position.y - sprite.getHeight()/2,
							 screen );
			}
		}
		
	}
	
	public void renderAabbs( Screen screen, Graphics2D g, ImageAtlas imageAtlas )
	{
		g.setStroke(new BasicStroke(1));
        g.setColor( Color.WHITE );
        
		int size = bullets.getSize();
		for( int i = 0; i < size; i++ )
		{
			BulletEntity b = bullets.get(i);
			
			if( b.isActive() )
			{
				g.drawRect( (int)b.hitBox.x1, (int)b.hitBox.y1, (int)b.hitBox.width, (int)b.hitBox.height );
			}
		}
		
	}
	
	
	public void spawnSpread( Vector2D position,
							 Vector2D gravity,
							 Vector2D target,
							 float angle, 
							 float speed, 
							 float acceleration, 
							 int stopCounter,
							 int goCounter,
							 boolean aim,
							 boolean seekPlayer,
							 Animator animator, 
							 Behavior behavior, 
							 Behavior nextBehavior, 
							 int aabbSize, 
							 int numbullets, 
							 float xRadius, 
							 float yRadius  )
	{
		
		float delta = (float) ((Math.PI*2) / (float)numbullets);
		
		
		
		for( int i = 0; i < numbullets; i++ )
		{
			
			
			angle += delta;
			
			if( animator.getMode() == Animator.Mode.ORIENTED )
			{
				animator.setAngle( (int)Math.toDegrees((double)angle) );
			}
			
			BulletEntity b = bullets.getFreeElement();
			
			if( b != null )
			{
				b.set( position.x + (float)Math.cos(angle) * xRadius,
					   position.y + (float)Math.sin(angle) * yRadius, 
					   angle, 
					   speed, 
					   acceleration,
					   stopCounter,
					   goCounter,
					   aim,
					   seekPlayer,
					   behavior, 
					   nextBehavior, 
					   animator, 
					   5 );
				b.gravity.set(gravity.x, gravity.y);
				b.target.set(target.x, target.y);
				b.velocity.set(0, 0);
				
			}
			
		}
		
	}
	
	
	public void spawnSpread( Vector2D position,
			 				 Vector2D gravity,
			 				 Vector2D target,
			 				 float angle, 
			 				 float speed, 
			 				 float acceleration, 
			 				 int stopCounter,
			 				 int goCounter,
			 				 boolean aim,
			 				 boolean seekPlayer,
			 				 Animator animator, 
			 				 Behavior behavior, 
							 Behavior nextBehavior, 
							 int aabbSize, 
			 				 int numBullets, 
			 				 float xRadius, 
			 				 float yRadius,
			 				 float speedDelta,
			 				 float sectorLength,
			 				 boolean symmetrical )
	{

		
		float delta = sectorLength / (float)numBullets;
		angle = (angle - (sectorLength)/2.0f) - (delta/2.0f);
		
		
		for( int i = 0; i < numBullets; i++ )
		{
		
			float centerFactor = symmetrical ? -Math.abs((i + 0.5f) - (numBullets)/2.0f) / (float)((numBullets)/2.0f) : i;
			float newSpeed = speed + (speedDelta * centerFactor); 
			angle += delta;
			
			if( animator.getMode() == Animator.Mode.ORIENTED )
			{
				animator.setAngle( (int)Math.toDegrees((double)angle) );
			}
			
			BulletEntity b = bullets.getFreeElement();
			
			if( b != null )
			{
				b.set( position.x + (float)Math.cos(angle) * xRadius,
					   position.y + (float)Math.sin(angle) * yRadius, 
					   angle, 
					   newSpeed, 
					   acceleration,
					   stopCounter,
					   goCounter,
					   aim,
					   seekPlayer,
					   behavior, 
					   nextBehavior, 
					   animator, 
					   5 );
				b.gravity.set(gravity.x, gravity.y);
				b.target.set(target.x, target.y);
				b.velocity.set(0, 0);
				
			}
			
		}

	}

	
	
	public void spawnRing( Vector2D position,
						   Vector2D gravity,
						   Vector2D target,
						   float angle, 
						   float speed, 
						   float acceleration, 
						   int stopCounter,
						   int goCounter,
						   boolean aim,
						   boolean seekPlayer,
						   Animator animator, 
						   Behavior behavior, 
						   Behavior nextBehavior, 
						   int aabbSize, 
						   int numbullets, 
						   float xRadius, 
						   float yRadius  )
	{
	
		float delta = (float) ((Math.PI*2) / (float)numbullets);
		float targetAngle = angle;
		
		if( animator.getMode() == Animator.Mode.ORIENTED )
		{
			animator.setAngle( (int)Math.toDegrees((double)targetAngle) );
		}
	
		for( int i = 0; i < numbullets; i++ )
		{
				
			BulletEntity b = bullets.getFreeElement();
			
			if( b != null )
			{
				b.set( position.x + (float)Math.cos(angle) * xRadius,
					   position.y + (float)Math.sin(angle) * yRadius, 
					   targetAngle, 
					   speed, 
					   acceleration,
					   stopCounter,
					   goCounter,
					   aim,
					   seekPlayer,
					   behavior, 
					   nextBehavior, 
					   animator, 
					   5 );
				b.gravity.set(gravity.x, gravity.y);
				b.target.set(target.x, target.y);
				b.velocity.set(0, 0);
				
			}
			
			angle += delta;
		}

	}


	public void spawnRing( Vector2D position,
			 			   Vector2D gravity,
			 			   Vector2D target,
			 			   float angle, 
			 			   float speed, 
			 			   float acceleration, 
			 			   int stopCounter,
			 			   int goCounter,
			 			   boolean aim,
			 			   boolean seekPlayer,
			 			   Animator animator, 
			 			   Behavior behavior, 
			 			   Behavior nextBehavior, 
			 			   int aabbSize, 
			 			   int numBullets, 
			 			   float xRadius, 
			 			   float yRadius,
			 			   float speedDelta,
			 			   float sectorLength,
			 			   boolean symmetrical )
	{
	
	
		float delta = sectorLength / (float)numBullets;
		float targetAngle = angle;
		angle = (angle - (sectorLength)/2.0f) - (delta/2.0f);
		
		if( animator.getMode() == Animator.Mode.ORIENTED )
		{
			animator.setAngle( (int)Math.toDegrees((double)targetAngle) );
		}
		
		for( int i = 0; i < numBullets; i++ )
		{
		
			float centerFactor = symmetrical ? -Math.abs((i + 0.5f) - (numBullets)/2.0f) / (float)((numBullets)/2.0f) : i;
			float newSpeed = speed + (speedDelta * centerFactor); 
			angle += delta;
			
			
			BulletEntity b = bullets.getFreeElement();
						
			if( b != null )
			{
				b.set( position.x + (float)Math.cos(angle) * xRadius,
					   position.y + (float)Math.sin(angle) * yRadius, 
					   targetAngle, 
					   newSpeed, 
					   acceleration,
					   stopCounter,
					   goCounter,
					   aim,
					   seekPlayer,
					   behavior, 
					   nextBehavior, 
					   animator, 
					   5 );
				b.gravity.set(gravity.x, gravity.y);
				b.target.set(target.x, target.y);
				b.velocity.set(0, 0);
				
			}
		
		}
	
	}

}	// end class
