package walsaip.vte.gui;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.DebugGL;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLJPanel;

import com.sun.opengl.util.Animator;

import edu.uprm.walsaip.vte.core.Drawable;
import edu.uprm.walsaip.vte.core.camera.Camera;
import edu.uprm.walsaip.vte.core.camera.CameraFactory;
import edu.uprm.walsaip.vte.core.datatypes.Angle;
import edu.uprm.walsaip.vte.core.datatypes.Light;
import edu.uprm.walsaip.vte.core.datatypes.Position;
import edu.uprm.walsaip.vte.core.datatypes.Vertex;
import edu.uprm.walsaip.vte.core.messagebus.Message;
import edu.uprm.walsaip.vte.core.messagebus.MessageBus;
import edu.uprm.walsaip.vte.core.messagebus.MessageListener;
import edu.uprm.walsaip.vte.core.model.TerrainModelFactory;
import edu.uprm.walsaip.vte.core.model.TerrainModel;
import edu.uprm.walsaip.vte.core.views.View;

/**
 * A 3D TerrainModel used in the Java OpenGL Demo
 * 
 * @author Ricardo Veguilla
 * 
 */
public class ViewPanel extends GLJPanel implements GLEventListener, View, MessageListener {

	
	private static final long serialVersionUID = 5189471471871484876L;

	
	private List<Drawable> objectList;
	
	private static Animator animator = new Animator();
	//private boolean initDone = false;
	//private boolean doInit = false;
	
	public ViewPanel() {
		super(getCapabilities());
	
		objectList = new ArrayList<Drawable>();
		
		ViewPanel.animator.add(this);
		ViewPanel.animator.setRunAsFastAsPossible(true);
		this.addGLEventListener(this);
		MessageBus.addListener(this,View.ID);
		
		initScene();
	}
	

	private void initScene() {
		Camera camera = CameraFactory.getDefaultCamera();
		CameraFactory.setCurrentCamera(camera);
		
		 //camera.getPosition().setPosition(new Vertex(0.0f, 0.0f, 2100.0f));
		// camera.getPosition().setAngle(new Angle(180.0f,0.0f,0.0f));
		 objectList.add(camera);
		
		 Light light = new Light(GL.GL_LIGHT0);
	     light.setPosition(new Position(new Vertex(0.0f, 5.0f, 0.0f),	new Angle()));
	     light.setAmbient(new Color(0.2f, 0.2f, 0.2f));

	     light.setDiffuse(new Color(0.5f, 0.5f, 0.5f));
	     light.setSpecular(new Color(0.0f, 1.0f, 0.0f));
	     objectList.add(light); 

		
		 objectList.add(TerrainModelFactory.getDefaultModel());
	   
	   //  initDone = true;
	}
	public void start() {
		if (!animator.isAnimating()) {
			animator.start();
			
		}
	}
	public void stop() {
		if (animator.isAnimating()) {
			animator.stop();
			
		}
	}
	private static GLCapabilities getCapabilities() {

		GLCapabilities capabilities = new GLCapabilities();
		capabilities.setHardwareAccelerated(true);
		capabilities.setDoubleBuffered(true);
		
		return capabilities;

	}

	public void init(GLAutoDrawable drawable) {

//		drawable.setGL(new DebugGL(drawable.getGL()));
		GL gl = drawable.getGL();
		
		
		for (Drawable object: objectList) {
			object.init(gl);
		}	
		
	}

	public void display(GLAutoDrawable drawable) {
		
		try{
//			drawable.setGL(new DebugGL(drawable.getGL()));
		GL gl = drawable.getGL();
		
		
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		
//		if (!initDone)
//			init(drawable);
//		else {
		
			gl.glPushMatrix();

			for (Drawable object: objectList) {
				object.render(gl);
			}
		
			gl.glPopMatrix();
			
//		}
		} catch(GLException e) {
			//System.out.print("GLException: ");
			e.printStackTrace();
			
			this.stop();
		}
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width,int height) {
			
		GL gl = drawable.getGL();
		
		float aspectRatio = (float) height / (float) width;
		
		MessageBus.sendMessage(new Message<Integer>(TerrainModel.ID,TerrainModel.WINDOW_HEIGHT, height));
		
		
		gl.glMatrixMode(GL.GL_PROJECTION);

		gl.glLoadIdentity();

		gl.glFrustum(-1.0f, 1.0f, -aspectRatio, aspectRatio, 1.0f, 1000000.0f);

		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();

	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
			boolean deviceChanged) {
	}

	public void addDrawable(Drawable d) {
		if (!objectList.contains(d))
			objectList.add(d);	
	}
	
	public void removeDrawable(Drawable d) {
		if (objectList.contains(d))
			objectList.remove(d);	
	}
	public void processEvent(Message<?> e) {
		String action = e.getName();
		Object value = e.getValue();
		
		if (action.equals(INIT)) {
			initScene();
		}
		else if (action.equals(START)) {
			start();
		}
		else if (action.equals(STOP)) {
			stop();
		}
		else if (action.equals(NEW)) {
			String filename = String.class.cast(value);
			MessageBus.sendMessage(new Message<Integer>(TerrainModel.ID,TerrainModel.WINDOW_HEIGHT, this.getHeight()));
			MessageBus.sendMessage(new Message<String>(TerrainModel.ID,TerrainModel.INIT, filename));
			
		}
		else if (action.equals(DESTROY)) {
			objectList.clear();
			//initDone = false;
		}
		
		
	}
}
