package extra;

import java.util.Random;

import javax.media.opengl.GL;

import com.sun.opengl.util.GLUT;

import de.rico.adventure.entity.character.NonPlayerCharacter;
import de.rico.adventure.main.ShootOut3DMain;
import de.rico.engine.effect.sound.SampledSound;
import de.rico.engine.enums.BoundingVolume;
import de.rico.engine.geometry.Point3D;
import de.rico.engine.geometry.collision.BoundingBox;
import de.rico.engine.geometry.modelloader.ms3d.ModelMS3DAscii;

public class BossManager
{		
	private SampledSound soundIncoming = new SampledSound("./incoming.wav",false);
	
	long cumulatedTime = 0;
	
	private Random random = null;
	
	private boolean bombsInitialized = false;
	
	private boolean firstLoop = true;
	
	private GLUT glut = null;
	
	public BossManager()
	{
		this.random = new Random();
		this.glut = new GLUT();		
	}
	
	/**
	 * Updates the boss manager
	 * @param elapsedTime time between two frames
	 */
	public void update(long elapsedTime)
	{
		// don't create bombs during first loop
		if(this.firstLoop == true)
		{
			this.firstLoop = false;
			return;
		}
		
		String levelName = ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getScriptId();
		NonPlayerCharacter boss = ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getCharacter(levelName+"_boss");	
		
		if(boss == null) return;			

		if(this.bombsInitialized == false)
		{
			this.initBombs(boss);
			this.bombsInitialized = true;
		}
		
		int bombsLeft = 0;
		for(NonPlayerCharacter npc : ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getCharacters())
		{
			if(npc.isEnabled() && npc.getScriptId().contains("_bomb"))
				bombsLeft++;
		}
		
		if(bombsLeft <= 0)
		{
			boss.setEnabled(true);
			this.cumulatedTime += elapsedTime;
			
			if(this.cumulatedTime >= boss.getTimeVulnerable())
			{
				this.cumulatedTime = 0L;
				this.reinitBombs(boss);
			}
		}
		else boss.setEnabled(false);
	}
	
	/**
	 * Creates new bombs falling down from the boss position
	 * @param boss the level boss
	 */
	private void initBombs(NonPlayerCharacter boss)
	{
		Point3D bossPosition = null;
		if(ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getCharacters().contains(boss))
			bossPosition = boss.getMesh().getPosition();
		else return;
		
		for(int i=0; i<boss.getNumberOfBombs(); i++)
		{
			ModelMS3DAscii mesh = new ModelMS3DAscii(BoundingVolume.BOX);
			mesh.load("./models/ms3d/borg_rocket/borg_rocket.txt", 0.007f);
			mesh.setTexUnit0("./models/ms3d/borg_rocket/borg_tex.png", true);
			NonPlayerCharacter bomb = new NonPlayerCharacter(mesh);
			bomb.setScriptId(boss.getRoom().getScriptId()+"_bomb"+i);											
						
			ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().addCharacter(bomb);						
		}								
		boss.getRoom().update(0);
		
		this.reinitBombs(boss);
	}

	/**
	 * Calculates the new initial position for the bomb
	 * @param boss
	 */
	private void reinitBombs(NonPlayerCharacter boss)
	{
		Point3D bossPosition = boss.getMesh().getPosition();
		
		for(NonPlayerCharacter npc : ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getCharacters())
		{
			if(npc.getScriptId().contains("_bomb") == false) continue;
			
			boolean positiveX = this.random.nextBoolean();
			boolean positiveZ = this.random.nextBoolean();
			
			int signX = positiveX? 1 : -1;
			int signZ = positiveZ? 1 : -1;
			
			npc.getMesh().setPosX(bossPosition.x+random.nextInt(6)*signX);
			npc.getMesh().setPosY(bossPosition.y-random.nextFloat()*5);
			npc.getMesh().setPosZ(bossPosition.z+random.nextInt(6)*signZ);			
			npc.getMesh().setDrawingEnabled(true);
			npc.setEnabled(true);
			
			npc.setHitPoints(boss.getBombHitPoints());
			npc.setBombDamage(boss.getBombDamage());
			npc.setBombSpeed(boss.getBombSpeed());
		}
		
		// add bombs now!	
		boss.getRoom().update(0);	
		
		this.soundIncoming.play();
	}
	
	/**
	 * Draws the shield of the managed boss
	 * @param gl
	 */
	public void draw(GL gl)
	{
		String levelName = ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getScriptId();
		NonPlayerCharacter boss = ShootOut3DMain.getInstance().getActiveChapter().getActiveRoom().getCharacter(levelName+"_boss");
		
		if(boss == null) return;
		
		if(boss.isEnabled() == true) return;
		
		BoundingBox shield = (BoundingBox)boss.getMesh().getBoundingVolume();
		
		
		gl.glPushAttrib(GL.GL_LIGHTING_BIT);
		{
			// use green color for the box
			float[] color = { 0f, 0.6f, 0f, 0.4f };
			gl.glDisable(GL.GL_LIGHTING);
			
			gl.glColor4fv(color, 0);
			
			gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT);
			{
				gl.glEnable(GL.GL_BLEND);
				gl.glDepthMask(false);			

				gl.glPushMatrix();
				{
					gl.glTranslatef(
							shield.getCenter().getX(), 
							shield.getCenter().getY(),
							shield.getCenter().getZ());
					
					gl.glRotatef(boss.getMesh().getRotX(), 1, 0, 0);
					gl.glRotatef(boss.getMesh().getRotY(), 0, 1, 0);
					gl.glRotatef(boss.getMesh().getRotZ(), 0, 0, 1);
					
					this.glut.glutSolidCube(shield.getLength()*1.1f);
				}
				gl.glPopMatrix();

				gl.glDepthMask(true);
				gl.glDisable(GL.GL_BLEND);				
			}	
			gl.glPopAttrib();
			
			gl.glEnable(GL.GL_LIGHTING);
		}
		gl.glPopAttrib();
	}
	
	/**
	 * Resets the bomb manager to its initial status
	 */
	public void reset()
	{
		this.bombsInitialized = false;
		this.cumulatedTime = 0L;
		this.firstLoop = true;
	}
}
