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

import static java.lang.System.out;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLContext;

import edu.uprm.walsaip.vte.core.ModuleInfo;
import edu.uprm.walsaip.vte.core.datatypes.terrain.TerrainData;
import edu.uprm.walsaip.vte.core.messagebus.Message;
import edu.uprm.walsaip.vte.core.messagebus.MessageBus;


public class VertexArrayRenderer implements Renderer {

	public static final String ID = VertexArrayRenderer.class.getSimpleName();
	public static final String TYPE = Renderer.ID;
	public static final ModuleInfo<VertexArrayRenderer> MODULE_INFO = new ModuleInfo<VertexArrayRenderer>() {
		
		protected void setInfo() {
			name = VertexArrayRenderer.ID;
			description = "Vertex Array Renderer";
			moduleClass = VertexArrayRenderer.class;
		
		}
		
		public boolean isSupported() {
			GL gl = GLContext.getCurrent().getGL();
			return gl.isFunctionAvailable("glDrawElements");  
		}
	};
	

	
	
	private VertexBufferData vboData;
	private boolean enabledArray[] = { false, false, false, false };

	private int primitiveType = GL.GL_TRIANGLES;//GL.GL_QUADS;
	private int polygonType = GL.GL_FILL;
	private boolean reinit = false;
	boolean colorMode = false;

	protected VertexArrayRenderer() {
		super();
		MessageBus.addListener(this,Renderer.ID);
	}

	
	public void init(GL gl) {
		
		out.printf("GL Driver: Vendor[ %s ] Renderer [ %s]",gl.glGetString(GL.GL_VENDOR),gl.glGetString(GL.GL_RENDERER));

		gl.setSwapInterval(1);
		gl.glEnable(GL.GL_CULL_FACE);
		gl.glCullFace(GL.GL_BACK);
		gl.glFrontFace(GL.GL_CW);

		gl.glEnable(GL.GL_LIGHTING);
		gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE);
		float globalAmbientLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
		gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, globalAmbientLight, 0);
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		gl.glClearDepth(1.0);
		gl.glDepthFunc(GL.GL_LEQUAL);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glShadeModel(GL.GL_SMOOTH);
		gl.glEnable(GL.GL_POLYGON_SMOOTH);
		gl.glEnable(GL.GL_COLOR_MATERIAL);
		gl.glColorMaterial(GL.GL_FRONT, GL.GL_AMBIENT);
	
		gl.glEnable(GL.GL_NORMALIZE);
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_FASTEST);
		gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_FASTEST);
		gl.glHint(GL.GL_POINT_SMOOTH_HINT, GL.GL_FASTEST);
		gl.glHint(GL.GL_POLYGON_SMOOTH_HINT, GL.GL_FASTEST);

		gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
		out.println(VertexArrayRenderer.ID+" Initialization: completed");
	}
	public void init(GL gl, TerrainData terrainData,  TerrainData imageData) {		
		


		init(gl);

		if (vboData == null || reinit) {
			vboData = new VertexBufferData(terrainData,imageData,primitiveType);
			reinit = false;
		}
		FloatBuffer vertexBuffer = vboData.getVertexBuffer();
		FloatBuffer colorBuffer = vboData.getColorBuffer();
		FloatBuffer normalBuffer = vboData.getNormalBuffer();
	

		if (vertexBuffer != null) {
			
			gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
			gl.glVertexPointer(4, GL.GL_FLOAT, 0, vertexBuffer);
			enabledArray[VertexBufferData.VERTEX_ID] = true;
		}
		
		

		if (colorBuffer != null) {
			if (colorMode)
				gl.glEnableClientState(GL.GL_COLOR_ARRAY);
			gl.glColorPointer(4, GL.GL_FLOAT, 0, colorBuffer);
			enabledArray[VertexBufferData.COLOR_ID] = true;
		}

		if (normalBuffer != null) {
			
			gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
			gl.glNormalPointer(GL.GL_FLOAT, 0, normalBuffer);
			enabledArray[VertexBufferData.NORMAL_ID] = true;
		}


		out.println(VertexArrayRenderer.ID+" Initialization: finished");

	}

	
	

	public int render(GL gl) {

		gl.glPushMatrix();
		gl.glPolygonMode(GL.GL_FRONT_AND_BACK, polygonType);
		if (vboData != null) {
			IntBuffer indexBuffer = vboData.getIndexBuffer();

			if (enabledArray[VertexBufferData.COLOR_ID] && colorMode)
				gl.glEnableClientState(GL.GL_COLOR_ARRAY);
			else {
				gl.glDisableClientState(GL.GL_COLOR_ARRAY);
				gl.glColor3f(0.42f, 0.34f, 0.26f);
			}

						
			gl.glDrawElements(vboData.getPrimitiveType(), indexBuffer.remaining(),GL.GL_UNSIGNED_INT, indexBuffer);

			
		}
		
		gl.glPopMatrix();
		return 0;
	}

	public void processEvent(Message<?> e) {
		
		
			String action = e.getName();
			Object value = e.getValue();
			if (action.equals("colorMode")) {
				colorMode = !(Float.class.cast(value) == 0.0f);

			} else if (action.equals("polygonType")) {
				polygonType = Float.class.cast(value).intValue();
			}
			else if (action.equals("reInit")) {
				reinit = true;
			}
		
	}


	public int addVertex(int idx, float xPos, float yPos, float zPos) {
		// TODO Auto-generated method stub
		return 0;
	}


	public int numTrianglesRendered() {
		// TODO Auto-generated method stub
		return 0;
	}


	public int render(GL gl, int mode, int numElements) {
		return 0;
		
	}


	public void render_frame_begin(GL gl) {
		// TODO Auto-generated method stub
		
	}


	public void render_frame_end(GL gl) {
		// TODO Auto-generated method stub
		
	}


	public void setupBuffers(int numTriangles) {
		// TODO Auto-generated method stub
		
	}


	
	public int addVertex(int idx, FloatBuffer vertex) {
		// TODO Auto-generated method stub
		return 0;
	}


	
	public int addVertex(int idx, float[] vertex) {
		// TODO Auto-generated method stub
		return 0;
	}


	@Override
	public int getNextTextureId() {
		// TODO Auto-generated method stub
		return 0;
	}

}
