package finale.boss;

import javax.media.opengl.GL;

import devUtil.Vector3;
import finale.Bullet;
import finale.Gun;

import object.Model;
import util.MP3;
import world.GameObject;

public class Xyrux extends GameObject {
	
	private God god;
	
	private int health;
	//MP3 newMusic;
	
	public Xyrux() {
		
		god = new God();
		
		god.setPosition(new Vector3(0, 17000, 2000));
		
		health = 100;
		
		//newMusic = new MP3("/audio/BGM/Archangel.mp3");
	}
	
	public void damage(int damage) {
		
		health -= damage;
		
//		if(health < 0)
//			health = 0;
		
		if(health <= 0) {
			
			Explosion explosion = new Explosion();
			explosion.setExplosion(god.getPosition(), 1000, 200);
			
			spawn.add(explosion);
			
			destroy();
		}
	}
	
	private int time;
	
	public void update() {
		
		if(god.getPosition().getY() > 1500 && time == 0)
			
			god.setPosition(new Vector3(
					god.getPosition().getX(),
					god.getPosition().getY() - 15,
					god.getPosition().getZ()));
		
		else {
			
			time++;
			
			god.setPosition(new Vector3(
					god.getPosition().getX(),
					1600 + Math.sin((double) time / 75) * 125,
					god.getPosition().getZ()));
			
			if(time == 650)
				god.extendRibbon();
			
			if(time > 750) {
				chaseTarget();
				attackTarget();
			}
			
			if(time == 2000)
				spawn.add(new Gun());
		}
		
		god.update();
		
		faceTarget();
	}
	
	private float rotation;

	private void faceTarget() {

		float xSpace = (float) (god.getPosition().getX() - camera.getXPosition());
		float zSpace = (float) (god.getPosition().getZ() - camera.getZPosition());

		float space = (float) Math.sqrt((xSpace * xSpace) + (zSpace * zSpace));

		float targetRotation = (float) Math.toDegrees(Math.asin(zSpace / space));
		
		if(xSpace <= 0)
			targetRotation += 90;
		
		else
			targetRotation += -targetRotation - 90;
		
		if(rotation < targetRotation) {
			
			rotation += .5;

			if(rotation > targetRotation)
				rotation = targetRotation;
		}

		if(rotation > targetRotation) {

			rotation -= .5;

			if(rotation < targetRotation)
				rotation = targetRotation;
		}
		
		god.setRotation(new Vector3(0, rotation, 0));
		
		god.setHealth(health);
	}
	
	private float speed = 4;
	
	private void chaseTarget() {
		
		float xSpace = (float) (god.getPosition().getX() - camera.getXPosition());
		float zSpace = (float) (god.getPosition().getZ() - camera.getZPosition());

		float space = (float) Math.sqrt((xSpace * xSpace) + (zSpace * zSpace));
		
		if(space > 250) {

			god.setPosition(new Vector3(
					god.getPosition().getX() - (xSpace / space) * speed,
					god.getPosition().getY(),
					god.getPosition().getZ() - (zSpace / space) * speed
					));
		}
	}
	
	private void attackTarget() {
		
		float xSpace = (float) (god.getPosition().getX() - camera.getXPosition());
		float ySpace = (float) (god.getPosition().getY() + 1400 - camera.getYPosition());
		float zSpace = (float) (god.getPosition().getZ() - camera.getZPosition());
		
		Vector3 direction = new Vector3(xSpace, ySpace, zSpace);
		direction = direction.getUnitVector();
		
		if(time > 1000 && (time - 1000) % 300 == 0) {
			
			Blaster blaster = new Blaster(
					new Vector3(god.getPosition().getX(), god.getPosition().getY() + 1400, god.getPosition().getZ()), 
					new Vector3(-direction.getX() * 25, -direction.getY() * 25, -direction.getZ() * 25),
					125);
			
			spawn.add(blaster);
			
			new MP3("/audio/FX/Missle.mp3").play(1);
		}
		
		if(time > 1000 && (time - 1000) % 50 == 0) {
			spawn.add(new Meteor());
		}
	}
	
	public void render(GL gl) {
		god.render(gl);
	}
	
	public void interact(GameObject object) {
		
		if(object instanceof Bullet) {
			
			Vector3 space = ((Bullet) object).getPosition();
			space.subtract(god.getPosition());
			
			if(space.getMagnitude() < 500) {
				
				damage(4);
				new MP3("/audio/FX/Uppercut.mp3").play(1);
				
				object.destroy();
			}
		}
	}
}

class God {
	
	Model body;
	Model ribbon;
	Model torus;
	
	Vector3 size;
	Vector3 position;
	Vector3 rotation;
	
	int health;
	
	public God() {
		
		body = new Model();
		
		body.setMode(true, false);
		body.parseObjectFile(ClassLoader.getSystemResourceAsStream(
						"visual/models/Xyrux.obj"));

		body.setPosition(0, 17500, 0);
		body.setSize(3000, 3000, 1000);
		
		body.setColor(1, .5f, 0);
		
		ribbon = new Model();
		
		ribbon.setMode(true, false);
		ribbon.parseObjectFile(ClassLoader.getSystemResourceAsStream(
						"visual/models/Xyrux Ribbon.obj"));

		ribbon.setPosition(0, 17500, 0);
		ribbon.setSize(3, 3, 1);
		
		ribbon.setColor(1, 0, 0);
		
		torus = new Model();
		
		torus.setMode(true, false);
		torus.parseObjectFile(ClassLoader.getSystemResourceAsStream(
						"visual/models/Xyrux Torus Knot.obj"));

		torus.setPosition(0, 17500, 0);
		torus.setSize(3, 3, 1);
		
		torus.setColor(0, 0, 1);
	}
	
	public void render(GL gl) {
		body.render(gl);
		ribbon.render(gl);
		torus.render(gl);
	}
	
	public void setPosition(Vector3 position) {
		
		body.setPosition(position);
		ribbon.setPosition(position);
		torus.setPosition(position);
		
		this.position = position;
	}
	
	public void extendRibbon() {
		ribbon.setSize(6, 6, 2);
	}
	
	public void extendTorus() {
		torusX = 6;
		torusY = 6;
		torusZ = 2;
	}
	
	public void setRotation(Vector3 rotation) {
		
		body.setRotation(new Vector3(
				rotation.getX(),
				rotation.getY() - 45,
				rotation.getZ()));
		
		ribbon.setRotation(rotation);
		torus.setRotation(rotation);
		
		this.rotation = rotation;
	}
	
	public Vector3 getPosition() {
		return position;
	}
	
	public Vector3 getRotation() {
		return rotation;
	}
	
	public void setHealth(int health) {
		
		//if(this.health < Integer.MAX_VALUE)
			this.health = health;
		
//		if(this.health <= 0) {
//			
//			this.health = Integer.MAX_VALUE;
//			
//			ribbon.setColor(1, 0, 0);
//			ribbon.setSize(3, 3, 1);
//			
//			extendRibbon();
//		}
		
//		if(ribbon.getXSize() > 2999 && torus.getXSize() == 3 &&
//				this.health == Integer.MAX_VALUE)
//			
//			extendTorus();
			
		if(ribbon.getXSize() > 2999 && torus.getXSize() == 3)
			extendTorus();
	}
	
	public int getHealth() {
		return health;
	}
	
	private float time;
	
	private double torusX = 3;
	private double torusY = 3;
	private double torusZ = 1;
	
	public void update() {
		
		time++;
		
		ribbon.setColor((float) health / 100, 0, 0);
		
		if(ribbon.getXSize() > 3 && ribbon.getXSize() < 3000)
			ribbon.setSize(ribbon.getXSize() + 6, ribbon.getYSize() + 6, ribbon.getZSize() + 2);
		
		torus.setSize(
				(float) (torusX * Math.sin(time / 100)),
				(float) torusY,
				(float) (torusZ * Math.cos(time / 100)));
		
		torus.setColor(0, (float) (1 - Math.cos(time / 100)), (float) (Math.cos(time / 100)));
		
		if(torusX > 3 && torusX < 2999) {
			
			torusX += 6;
			torusY += 6;
			torusZ += 2;
		}
	}
}