package edu.uprm.walsaip.vte.core.camera;

//import static walsaip.uprmvte.objects.Angle.YAW;
//import static walsaip.uprmvte.objects.Angle.PITCH;
//import static walsaip.uprmvte.objects.Angle.ROLL;
import static edu.uprm.walsaip.vte.core.datatypes.Vector.X;
import static edu.uprm.walsaip.vte.core.datatypes.Vector.Y;
import static edu.uprm.walsaip.vte.core.datatypes.Vector.Z;
import static java.lang.System.out;

import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;

import edu.uprm.walsaip.vte.core.ModuleInfo;
import edu.uprm.walsaip.vte.core.datatypes.Light;
import edu.uprm.walsaip.vte.core.datatypes.Position;
import edu.uprm.walsaip.vte.core.messagebus.Message;
import edu.uprm.walsaip.vte.core.messagebus.MessageBus;
/**
 * Class that represents the virtual camera.
 * 
 * @author Ricardo Veguilla (veguilla@ece.uprm.edu)
 * 
 */
public class LookAtCamera implements Camera {

	/*public static final CameraInfo<LookAtCamera> MODULE_INFO = new CameraInfo<LookAtCamera>(
			 "A Generic Camera Implementation.",
			LookAtCamera.class);
*/
	
	public static final String ID = LookAtCamera.class.getSimpleName();
	public static final String TYPE = Camera.ID;
	
	public static final ModuleInfo<LookAtCamera> MODULE_INFO = new ModuleInfo<LookAtCamera>() {
		protected void setInfo() {
			name = LookAtCamera.ID;
			description = "A Tracking Camera Implementation.";
			moduleClass = LookAtCamera.class;
			supported = true;
		}
	};
		
	
	private Position position;
	private Light light;
	private GLU glu;
	/**
	 * Default constructor.
	 */
	private float deltaAngle = 1.0f;

	private float movementOffset = 5.0f;

	protected LookAtCamera() {
		super();
		this.position = new Position();
		this.light = new Light(GL.GL_LIGHT1);
		this.glu = new GLU();
		MessageBus.addListener(this,Camera.ID);
	}

	public void init(GL gl) {
		out.println(LookAtCamera.ID+" Initialization: completed");
	}

	public int render(GL gl) {

		
		light.init(gl);

		light.setConstantAttenuation(0.8f);
		light.render(gl);
		float [] eye= position.getPosition().getAsArray();
		float [] up = position.getUp().getAsArray();
		float [] center = { 0.0f, 0.0f,0.f };
		glu.gluLookAt(eye[X], eye[Y], eye[Z],
				center[X], center[Y], center[Z], 
				up[X], up[Y], up[Z]);
		
		
		//gl.glMultMatrixf(cameraMatrix, 0);
		return 0;
	}

	

	/**
	 * @return Returns the position.
	 */
	public Position getPosition() {
		return position;
	}

	/**
	 * @param position
	 *            The position to set.
	 */
	public void setPosition(Position position) {
		this.position = position;
	}

	public Light getLight() {

		return light;
	}

	public void setLight(Light light) {
		this.light = light;
	}

	public void processEvent(Message<?> e) {
		
		
			String action = e.getName();
			Object value = e.getValue();

			if (action.equals("moveForward")) {
				position.getPosition().multiplyAndAdd(position.getForward(),
						-movementOffset);
			} else if (action.equals("moveBackward")) {
				position.getPosition().multiplyAndAdd(position.getForward(),
						movementOffset);
			} else if (action.equals("moveLeft")) {
				position.getPosition().multiplyAndAdd(position.getRight(),
						movementOffset);
			} else if (action.equals("moveRight")) {
				position.getPosition().multiplyAndAdd(position.getRight(),
						-movementOffset);
			} else if (action.equals("moveUp")) {
				position.getPosition().multiplyAndAdd(position.getUp(),
						movementOffset);
			} else if (action.equals("moveDown")) {
				position.getPosition().multiplyAndAdd(position.getUp(),
						-movementOffset);
			} else if (action.equals("rotateUp")) {
				position.rotateAroundAxisX(deltaAngle / 3.0f);

			} else if (action.equals("rotateDown")) {
				position.rotateAroundAxisX(-deltaAngle / 3.0f);
			} else if (action.equals("rotateLeft")) {
				position.rotateAroundAxisY(-deltaAngle);
			} else if (action.equals("rotateRight")) {
				position.rotateAroundAxisY(deltaAngle);
			} else if (action.equals("rollLeft")) {

				position.rotateAroundAxisZ(-deltaAngle);
			} else if (action.equals("rollRight")) {
				position.rotateAroundAxisZ(deltaAngle);
			} else if (action.equals("setMovementOffset")) {
				this.movementOffset = Float.class.cast(value);
			} else if (action.equals("setDetlaAngle")) {
				this.deltaAngle = Float.class.cast(value);
			}
			out.println(position.getAngle());
		
	}

}
