package icarus;

import java.util.ArrayList;

import javax.media.opengl.GL;

import devUtil.Vector3;

import object.Model;

import util.MP3;
import world.GameObject;

public class Sky extends GameObject {
	
	ArrayList<Cloud> clouds;
	
	public Sky() {
		addClouds();
	}
	
	int time;
	int beepTime;
	
	float gravity;
	
	public void update() {
		
		for(int i = 0; i < clouds.size(); i++) {
			
			clouds.get(i).update();
			
			if(clouds.get(i).isGoal()) {
				
				Vector3 space = clouds.get(i).getPosition();
				space.subtract(camera.getPosition());
				
				float distance = (float) space.getMagnitude();
				
				beepTime = (int) ((distance / 25) + (1000 * (gravity / 5)));
				
				if(beepTime > 1000)
					beepTime = 1000;
				
				if(beepTime < 1)
					beepTime = 1;
			}
		}
		
		for(int i = 0; i < clouds.size(); i++) {
			
			if(clouds.get(i).doesCollide(
					(float) camera.getXPosition(),
					(float) camera.getYPosition(),
					(float) camera.getZPosition()) &&
					clouds.get(i).isGoal() &&
					gravity == 0) {
				
				gravity = .01f;
			}
			
			if(clouds.get(i).doesCollide(
					(float) camera.getXPosition(),
					(float) camera.getYPosition(),
					(float) camera.getZPosition()) &&
					!clouds.get(i).isGoal()) {
				
				clouds.remove(i);
				i--;
			}
		}
		
		time++;
		
		if(time >= beepTime) {
			
			new MP3("/audio/FX/Bell.mp3").play(1);
			
			time = 0;
		}
		
		if(gravity > 0)
			gravity += .01;
		
		camera.setYPosition(camera.getYPosition() - gravity);
		
		if(gravity >= 7.5) {
			setTriggeredGameState("Level, Home");
			endScene();
		}
	}
	
	public void addClouds() {
		
		clouds = new ArrayList<Cloud>();
		
		for(int i = 0; i < 10; i++) {
			
			Cloud cloud = new Cloud();
			
			float size = (float) (Math.random() * 500) + 100;
			cloud.setSize(size, size / 4, size);
			
			cloud.setPosition(
					(float) (Math.random() * 5000) - 2500,
					(float) (Math.random() * 5000) - 2500,
					(float) (Math.random() * 5000) - 2500);
			
			cloud.setSpeed(new Vector3(
					(float) (Math.random() * 4) - 2,
					0,
					(float) (Math.random() * 4) - 2));
			
			clouds.add(cloud);
		}
		
		clouds.get((int) Math.random() * clouds.size()).makeGoal();
	}
	
	public void render(GL gl) {
		
		float darkness = (5 - gravity) / 5;
		
		if(darkness < 0)
			darkness = 0;
		
		if(darkness > 1)
			darkness = 1;
		
		gl.glClearColor(.4f * darkness, .4f * darkness, 1f * darkness, 1f);
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		
		for(int i = 0; i < clouds.size(); i++) {
			clouds.get(i).setColor(darkness, darkness, darkness);
			clouds.get(i).render(gl);
		}
	}
}

class Cloud {
	
	private Model cloud;
	
	private Vector3 speed;
	private double time;
	
	private boolean isGoal;
	
	public Cloud() {
		
		cloud = new Model();
		cloud.setMode(true, false);

		cloud.parseObjectFile(
				ClassLoader.getSystemResourceAsStream(
						"visual/models/Cloud.obj"));
		
		cloud.setColor(1, 0, 0);
		cloud.setSize(50, 25, -50);
		
		speed = new Vector3(0, 0, 0);
	}
	
	public void setPosition(float x, float y, float z) {
		cloud.setPosition(x, y, z);
	}
	
	public Vector3 getPosition() {
		
		return new Vector3(
				cloud.getXPosition(),
				cloud.getYPosition(),
				cloud.getZPosition());
	}
	
	public void setSize(float x, float y, float z) {
		cloud.setSize(x, y, z);
	}
	
	public void setSpeed(Vector3 speed) {
		this.speed = speed;
	}
	
	public void setColor(float red, float green, float blue) {
		cloud.setColor(red, green, blue);
	}
	
	public void makeGoal() {
		isGoal = true;
	}
	
	public boolean isGoal() {
		return isGoal;
	}
	
	public void update() {
		
		time += .001;
		
		cloud.setPosition(
				cloud.getXPosition() + (float) speed.getX() * (float) Math.cos(time),
				cloud.getYPosition() + (float) speed.getY() * (float) Math.cos(time),
				cloud.getZPosition() + (float) speed.getZ() * (float) Math.cos(time));
	}
	
	public void render(GL gl) {
		cloud.render(gl);
	}
	
	public boolean doesCollide(float x, float y, float z) {
		
		if(Math.abs(cloud.getXPosition() - x) < cloud.getXSize() / 2 &&
				Math.abs(cloud.getYPosition() - y) < cloud.getYSize() / 2 &&
				Math.abs(cloud.getZPosition() - z) < cloud.getZSize() / 2)
			
			return true;
		
		return false;
	}
}