package net.phatcode.rel;

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

import net.phatcode.rel.math.Utils;
import net.phatcode.rel.math.Vector2D;
import net.phatcode.rel.utils.ImageAtlas;
import net.phatcode.rel.utils.Keyboard;
import net.phatcode.rel.utils.LinkedArray;
import net.phatcode.rel.utils.Sonics;

public class ShipEntity extends Entity
{
	
	public static enum AnimationDirection
	{
		LEFT,
		NEUTRAL,
		RIGHT
	}
	
	public static final int MAX_HIT_COUNTER = 3;
	public static final int MAX_SHOTS = 128;
	public static final int MAX_SHOT_DELAY = 4;
	
	public LinkedArray<ShotEntity> 
			shots = new LinkedArray<ShotEntity>( MAX_SHOTS, new ShotEntity() );;
	
	private int shotDelay = 0;
	private int shotFrame = 0;
	private boolean isFiring = false;
	
	private int baseFrame;
	private int numFrames;
	private int frame;
	
	private float directionLerp = 0;
	private AnimationDirection animationDirection = AnimationDirection.NEUTRAL;
	private RenderMode renderMode = RenderMode.NORMAL;
	private int hitCounter = 0;
	
	private Animator jetExhaust;
	private Animator shotExhaust;
	
	
	public ShipEntity()
	{
		
		int size = shots.getSize();
		for( int i = 0; i < size; i++ )
		{
			shots.set( i, new ShotEntity() );
		}
		
		position = new Vector2D( Constants.SCREEN_WIDTH/2, Constants.SCREEN_HEIGHT - 50 );
		direction = new Vector2D();
		speed = 3.0f;
		
		jetExhaust = new Animator( 32, 6 );
		shotExhaust = new Animator( 38, 6 );
		
		counter = 0;
		baseFrame = 3;
		numFrames = 4;
		frame = 0;
		active = true;
		
		animationDirection = AnimationDirection.NEUTRAL;
		
		initHitBox( position.x, position.y, 20, 40 );
		hitBox.resize(0.3f);
		behavior = new BehaviorLinear();
		
		
	}
	
	private void animate()
	{
		
		jetExhaust.update();
		shotExhaust.update();
		
		if( animationDirection == AnimationDirection.NEUTRAL )
		{
			if( directionLerp > 0 ) 
			{
				directionLerp -= 0.05f;
				directionLerp = Utils.clamp( directionLerp, 0.0f, 1.0f );
				float f = Utils.lerpSmooth( 0, numFrames-1, directionLerp );
				frame = (int)f;
			}
			else
			{
				directionLerp += 0.05f;
				directionLerp = Utils.clamp( directionLerp, -1.0f, 0.0f );
				float f = Utils.lerpSmooth( 0, numFrames-1, -directionLerp );
				frame = (int)-f;
			}
			
		}
		else
		{
			if( animationDirection == AnimationDirection.LEFT )
			{
				directionLerp -= 0.05f;
				directionLerp = Utils.clamp( directionLerp, -1.0f, 0.0f );
				float f = Utils.lerpSmooth( 0, numFrames-1, -directionLerp );
				frame = (int)-f;
			}
			else if( animationDirection == AnimationDirection.RIGHT )
			{
				directionLerp += 0.05f;
				directionLerp = Utils.clamp( directionLerp, 0.0f, 1.0f );
				float f = Utils.lerpSmooth( 0, numFrames-1, directionLerp );
				frame = (int)f;
			}
				
		}
		
	}
	
	@Override
	public void update()
	{
		
		counter++;
		
		behavior.update( this );
		
		position.x = Utils.clamp( position.x, 10, Constants.SCREEN_WIDTH - 10 );
		position.y = Utils.clamp( position.y, 20, Constants.SCREEN_HEIGHT - 20 );
		
		updateHitBox();
	
		updateShots();
		
		animate();
		
		direction.x = 0;
		direction.y = 0;
		
		animationDirection = AnimationDirection.NEUTRAL;
		
		if( renderMode != RenderMode.NORMAL )
		{
			hitCounter--;
			if( hitCounter == 0 )
			{
				renderMode = RenderMode.NORMAL;
			}
		}
		
		
		if( Keyboard.getInstance().isKeyPressed( KeyEvent.VK_LEFT ) )
		{
			direction.x = -1;
	    	animationDirection = AnimationDirection.LEFT;
		}
		
		if( Keyboard.getInstance().isKeyPressed( KeyEvent.VK_RIGHT ) )
		{
			direction.x = 1;
	    	animationDirection = AnimationDirection.RIGHT;
		}
		
		if( Keyboard.getInstance().isKeyPressed( KeyEvent.VK_UP ) )
		{
			direction.y = -1;
	    }
		
		if( Keyboard.getInstance().isKeyPressed( KeyEvent.VK_DOWN ) )
		{
			direction.y = 1;
		}
		
		
		isFiring = false;
		if( Keyboard.getInstance().isKeyPressed( KeyEvent.VK_SPACE ) )
		{
			shotDelay--;
			isFiring = true;
			if( shotDelay < 0 ) 
			{
				shotDelay = MAX_SHOT_DELAY;
				shots.getFreeElement().set( position.x - 10, position.y-20, 
										    20 + shotFrame,
										    (float)Math.toRadians(262) );
				shots.getFreeElement().set( position.x + 10, position.y-20, 
					    					20 + shotFrame,
					    					(float)Math.toRadians(278) );
				
				shots.getFreeElement().set( position.x, position.y-20, 
    										17 + shotFrame,
    										(float)Math.toRadians(270) );
				
				shots.getFreeElement().set( position.x, position.y-20, 
											23 + shotFrame,
											(float)Math.toRadians(counter),
											ShotEntity.TYPE.WAVE );
				shots.getFreeElement().set( position.x, position.y-20, 
											23 + shotFrame,
											(float)(Math.PI + Math.toRadians(counter)),
											ShotEntity.TYPE.WAVE );

				shotFrame = (shotFrame + 1) % 3;
				
				Sonics.getInstance().playEffect("media/shot.wav");
				
			}
			
		}
		else
		{
			shotDelay = 0;
		}
		
	}
	
	
	@Override
	public void render( Screen screen, Graphics2D g, ImageAtlas imageAtlas )
	{
		if( active )
		{
			//shots
			renderShots( screen, g, imageAtlas );
		
			// jet
			g.drawImage( imageAtlas.getSprite(jetExhaust.getFrame()), 
					 	 (int)position.x - imageAtlas.getSprite(jetExhaust.getFrame()).getWidth()/2,
					 	 (int)position.y + 15,
					 	 screen );
			if( (isFiring)  )
			{
				// shot exhaust
				g.drawImage( imageAtlas.getSprite(shotExhaust.getFrame()), 
					 	 (int)position.x - 10 - imageAtlas.getSprite(shotExhaust.getFrame()).getWidth()/2,
					 	 (int)position.y - 20,
					 	 screen );
				g.drawImage( imageAtlas.getSprite(shotExhaust.getFrame()), 
					 	 (int)position.x + 10 - imageAtlas.getSprite(shotExhaust.getFrame()).getWidth()/2,
					 	 (int)position.y - 20,
					 	 screen );
			}
		
			// ship
			int drawFrame = baseFrame + frame;
			if( hitCounter > 0 ) drawFrame += (numFrames*2 - 1);
			
			g.drawImage( imageAtlas.getSprite(drawFrame), 
					 (int)position.x - imageAtlas.getSprite(drawFrame).getWidth()/2,
					 (int)position.y - imageAtlas.getSprite(drawFrame).getHeight()/2,
					 screen );
	
		}
		
	}
	
	public void renderAabb( Screen screen, Graphics2D g, ImageAtlas imageAtlas )
	{
		if( active )
		{
			g.setStroke(new BasicStroke(1));
	        g.setColor( Color.WHITE );
            g.drawRect( (int)hitBox.x1, (int)hitBox.y1, (int)hitBox.width, (int)hitBox.height );
            
		}
		
	}
	
	public void setRenderMode( RenderMode renderMode)
	{
		this.renderMode = renderMode;
		this.hitCounter = MAX_HIT_COUNTER;
	}
	
	public void updateShots()
	{
		
		int size = shots.getSize();
		for( int i = 0; i < size; i++ )
		{
			ShotEntity shot = shots.get(i);
			
			if( shot.isActive() )
			{
				shot.update();
				if( shot.position.y < -40 )
				{
					shot.kill() ;
					shots.remove(i);
				}
			}
		}
	
	}

	public void renderShots( Screen screen, Graphics2D g, ImageAtlas imageAtlas )
	{
		
		int size = shots.getSize();
		for( int i = 0; i < size; i++ )
		{
			ShotEntity shot = shots.get(i);
			
			if( shot.isActive() )
			{
			
				BufferedImage sprite = imageAtlas.getSprite(shot.getFrame());
				g.drawImage( sprite, 
						 	 (int)shot.position.x - sprite.getWidth()/2,
						 	 (int)shot.position.y - sprite.getHeight()/2,
						 	 screen );
		
			}
		
		}
	
	}

	public int getActiveShots()
	{
		return shots.getActiveElements();
	}
	
	
}
