package net.phatcode.rel;

import net.phatcode.rel.math.Utils;
import net.phatcode.rel.math.Vector2D;
import net.phatcode.rel.utils.AABB;
import net.phatcode.rel.utils.Explosion;

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

public class BulletEntity extends Entity
{

	private int stopCounter = 0;
	private int goCounter = 0;
	
	private boolean aim = false;
	private boolean seekPlayer = false;
	
	private Behavior nextBehavior = behavior;
	
	private int aabbSize = 0;
	
	public BulletEntity()
	{
		active = false;
	}
	
	public BulletEntity( BulletEntity b )
	{
		
		position = new Vector2D( b.position );
		direction = new Vector2D( b.direction );
		gravity = new Vector2D( b.gravity );
		target = new Vector2D( b.target );
		
		speed = b.speed;
		acceleration = b.acceleration;
		angle = b.angle;
		
		active = b.active;
		counter = b.counter;
		
		animator = new Animator(b.animator);
		
		behavior = new Behavior(b.behavior);
		nextBehavior = new Behavior(b.nextBehavior);
		hitBox = new AABB(b.hitBox);
		
		stopCounter = b.stopCounter;
		goCounter = b.goCounter;
		
		aim = b.aim;
		seekPlayer = b.seekPlayer;
	
	}
	
	public BulletEntity( float x, float y, float angle, float speed )
	{
		position = new Vector2D( x, y );
		direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		animator = new Animator();
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;
		active = true;
		
	}
	
	public BulletEntity( float x, float y, float angle, float speed, Animator animator )
	{
		position = new Vector2D( x, y );
		direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = animator;
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;
		active = true;
	}
	
	public BulletEntity( Vector2D position, float angle, float speed )
	{
		this.position = position;
		this.direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = new Animator();
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;
		active = true;
	}
	
	public BulletEntity( Vector2D position, float angle, float speed, Animator animator )
	{
		this.position = position;
		this.direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = animator;
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;
		active = true;
		
	}
	
	public BulletEntity( Vector2D position, float angle, float speed, Animator animator, Behavior behavior )
	{
		this.position = position;
		this.direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = animator;
		this.behavior = behavior;
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;

		active = true;
	}
	
	public BulletEntity( Vector2D position, float angle, float speed, 
			 			 Animator animator, Behavior behavior, int aabbSize )
	{
		this.position = position;
		this.direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = animator;
		this.behavior = behavior;
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;		
		active = true;
		initHitBox( position.x, position.y, aabbSize, aabbSize );
		this.aabbSize = aabbSize;
	}

	public BulletEntity( Vector2D position, float angle, float speed, float acceleration, 
						 Animator animator, Behavior behavior, int aabbSize )
	{
		this.position = position;
		this.direction = new Vector2D( (float)Math.cos(angle), (float)Math.sin(angle) );
		this.animator = animator;
		this.behavior = behavior;
		this.nextBehavior = behavior;
		
		this.angle = angle;
		this.speed = speed;
		this.acceleration = acceleration;
		
		active = true;
		initHitBox( position.x, position.y, aabbSize, aabbSize );
		this.aabbSize = aabbSize;
	}

	public void set( float x,
					 float y, 
					 float angle, 
					 float speed, 
					 float acceleration,
					 int stopCounter,
					 int goCounter,
					 boolean aim,
					 boolean seekPlayer,
			 		 Behavior behavior, 
			 		 Behavior nextBehavior, 
			 		 Animator animator, 
			 		 int aabbSize )
	{
		
		
		this.counter = 0;
		this.active = true;
		
		this.position.x = x;
		this.position.y = y;
		this.direction.set( (float)Math.cos(angle), (float)Math.sin(angle) );
		
		this.angle = angle;
		this.speed = speed;
		this.acceleration = acceleration;
		
		this.stopCounter = stopCounter;
		this.goCounter = goCounter + stopCounter;
		
		this.aim = aim;
		this.seekPlayer = seekPlayer;
		
		this.behavior = behavior;
		this.nextBehavior = nextBehavior;
		
		this.animator.reset(animator);
		this.aabbSize = aabbSize;
		
		initHitBox( x, y, aabbSize, aabbSize );
		
	}

	public void update( Vector2D playerPosition )
	{
		counter++;
		if( counter == stopCounter )
		{
			behavior = Behaviors.behaviorStop;
		}
		else if( counter == goCounter )
		{
			if( aim )
			{
				angle = Vector2D.angleBetween( position, this.target );
				direction.set( (float)Math.cos(angle), (float)Math.sin(angle) );
				animator.setAngle( Utils.wrap((int)Math.toDegrees((double)angle), 0, 359) );
			}
			else if( seekPlayer )
			{
				angle = Vector2D.angleBetween( position, playerPosition );
				direction.set( (float)Math.cos(angle), (float)Math.sin(angle) );
				animator.setAngle( Utils.wrap((int)Math.toDegrees((double)angle), 0, 359) );
			}
			
			behavior = nextBehavior;
			
		}
		
		behavior.update(this);
		animator.update();
		updateHitBox();
	}
	
	@Override
	public void explode()
	{
		Explosion.getInstance().spawn( position, 
									   direction,
									   speed/2, 
									   18, 6 );	
		kill();
	}
	
	
	public int getFrame()
	{
		return animator.getFrame();
	}
	
	public void setStopCounter( int stopCounter )
	{
		this.stopCounter = stopCounter;
	}

	public void setGoCounter( int goCounter )
	{
		this.goCounter = goCounter + stopCounter;
	}

	public void setAim( boolean aim )
	{
		this.aim = aim;
	}

	public void setSeekPlayer( boolean seekPlayer )
	{
		this.seekPlayer = seekPlayer;
	}

	public void setNextBehavior( Behavior nextBehavior )
	{
		this.nextBehavior = nextBehavior;
	}

	public int getStopCounter()
	{
		return stopCounter;
	}

	public int getGoCounter()
	{
		return goCounter;
	}

	public boolean isAim()
	{
		return aim;
	}

	public boolean isSeekPlayer()
	{
		return seekPlayer;
	}

	public Behavior getNextBehavior()
	{
		return nextBehavior;
	}

	public int getAabbSize()
	{
		return aabbSize;
	}

	public void setAabbSize(int aabbSize)
	{
		this.aabbSize = aabbSize;
	}
	
	
}
