package pl.vorg.mowa.core.graphics;

import javax.media.opengl.GL;

/**
 * Klasa reprezentujaca obiekt 3d. Posiada informacje o punktach z których złożony jest obiekt, 
 * tego czy składa sie z trójkątów czy czworokątow i pozwala na jego wyświetlenie.
 * 
 * @author vorg
 *
 */
public class Geometry {
	private VertexStream vertexStream;
	private String name;
	private PrimitiveType primitiveType = PrimitiveType.None;
	private BoundingBox boundingBox = new BoundingBox();
	
	//vbo
	int[] ids = new int[3];
	boolean vboInit = false;

	public VertexStream getVertexStream() {
		return vertexStream;
	}

	public void setVertexStream(VertexStream vertexStream) {
		this.vertexStream = vertexStream;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public PrimitiveType getPrimitiveType() {
		return primitiveType;
	}

	public void setPrimitiveType(PrimitiveType type) {
		this.primitiveType = type;
	}
	
	public void display(GL gl) {
		displayImmediately(gl);
	}
	
	private void displayImmediately(GL gl) {
		if (vertexStream == null) {
			return;
		}
		int[] indices = vertexStream.getIndexBuffer().getBuffer();
		FloatVertexAttrib posAttrib = (FloatVertexAttrib)vertexStream.getAttribByName("pos");				
		float[] positions = (posAttrib != null) ? posAttrib.getBuffer() : null;
		FloatVertexAttrib normalAttrib = (FloatVertexAttrib)vertexStream.getAttribByName("normal");
		float[] normals = (normalAttrib != null) ? normalAttrib.getBuffer() : null;
		FloatVertexAttrib texCoord0Attrib = (FloatVertexAttrib)vertexStream.getAttribByName("texCoord0");
		float[] texCoords0 = (texCoord0Attrib != null) ? texCoord0Attrib.getBuffer() : null;
		FloatVertexAttrib tangentAttrib = (FloatVertexAttrib)vertexStream.getAttribByName("tangent");
		float[] tangents = (tangentAttrib != null) ? tangentAttrib.getBuffer() : null;
	
		gl.glBegin(primitiveType.toGL());
		for(int i=0; i<indices.length; i++) {			
			if (normals != null) {
				gl.glNormal3fv(normals, indices[i]*3);
			}
			if (texCoords0 != null) {
				gl.glTexCoord2fv(texCoords0, indices[i]*2);
			}
			if (tangents != null) {
				gl.glVertexAttrib3fv(ShaderProgram.TANGENT_ATTRIB_LOCATION, tangents, indices[i]*3);
			}
			gl.glVertex3fv(positions, indices[i]*3);
		}
		gl.glEnd();
		
		/*
 		//to powinno byc zrobione na VBO albo chociaz VertexArrays ale na razie nie sa one supportowane w JOGL dla OSX
		if (!vboInit) {
			vboInit = true;
			gl.glGenBuffers( 3, ids, 0);   // get names
			
			FloatBuffer posFB = BufferUtil.newFloatBuffer(positions.length);
	        FloatBuffer normalFB = BufferUtil.newFloatBuffer(normals.length);
	        FloatBuffer texCoord0FB = BufferUtil.newFloatBuffer(texCoords0.length);
	        
	        posFB.put(positions);
	        normalFB.put(normals);
	        texCoord0FB.put(texCoords0);
	        
			gl.glBindBuffer( GL.GL_ARRAY_BUFFER, ids[0] );
			gl.glBufferData( GL.GL_ARRAY_BUFFER, positions.length*BufferUtil.SIZEOF_FLOAT, posFB, GL.GL_STATIC_DRAW );
			gl.glVertexPointer( 3, GL.GL_FLOAT, 0, (Buffer) null );      
		        
		    //gl.glBindBuffer( GL.GL_ARRAY_BUFFER, ids[1] );
		    //gl.glBufferData( GL.GL_ARRAY_BUFFER, normals.length*BufferUtil.SIZEOF_FLOAT, normalFB, GL.GL_STATIC_DRAW );
		    //gl.glNormalPointer( 3, 0, (Buffer) null  );
	        
		    //gl.glBindBuffer( GL.GL_ARRAY_BUFFER, ids[2] );
		    //gl.glBufferData( GL.GL_ARRAY_BUFFER, texCoords0.length*BufferUtil.SIZEOF_FLOAT, texCoord0FB, GL.GL_STATIC_DRAW );
		    //gl.glTexCoordPointer( 3, GL.GL_FLOAT, 0, (Buffer) null  );
		    
		}
		else {
			gl.glEnableClientState (GL.GL_VERTEX_ARRAY);     
	        gl.glEnableClientState (GL.GL_NORMAL_ARRAY);
	        gl.glEnableClientState (GL.GL_TEXTURE_COORD_ARRAY);
	        
	        //gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, ids[0] );	                 	        
	        //gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, ids[1] );	       
	        //gl.glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, ids[2] );
	        	        
	        gl.glDrawArrays(GL.GL_TRIANGLES, 0, positions.length); // draw everything (six vertices)
	        
	        gl.glDisableClientState (GL.GL_VERTEX_ARRAY);
	        gl.glDisableClientState (GL.GL_NORMAL_ARRAY);
	        gl.glDisableClientState (GL.GL_TEXTURE_COORD_ARRAY);
		}
*/	
		
//		if (positions != null) {
//			gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
//			FloatBuffer buf = BufferUtil.newFloatBuffer(positions.length);//FloatBuffer.allocate(positions.length);
//			buf.put(positions);
//			gl.glVertexPointer(3, GL.GL_FLOAT, 0, buf);
//		}	
		
		//if (normals != null) {
			//gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
			//FloatBuffer buf = FloatBuffer.wrap(normals);
			//gl.glNormalPointer(GL.GL_FLOAT, 3, buf);
		//}	
		
		//if (texCoords0 != null) {
			//gl.glClientActiveTexture(GL.GL_TEXTURE0); 	
			//gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
			//FloatBuffer buf = FloatBuffer.wrap(texCoords0);
			//gl.glTexCoordPointer(2, GL.GL_FLOAT, 2, buf); 				
		//}	
		
		//gl.glDrawElements(primitiveType.toGL(), vertexStream.getIndexBuffer().getBuffer().length, GL.GL_INT, stream.getIndices());

		
		//attrib = stream.getAttrib("TANGENT", TYPE_VEC3);
		//if (attrib) {
		//	glEnableVertexAttribArrayARB(3);
		//	glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, attrib->getStride(), attrib->getBuffer()); 
		//}	
		
		
//		//normals		
//		gl.glDisable(GL.GL_LIGHTING);
//		gl.glDisable(GL.GL_TEXTURE_2D);
//		gl.glColor3ub((byte)255, (byte)0, (byte)0);
//		gl.glBegin(GL.GL_LINES);
//		for(int i=0; i<indices.length; i++) {
//			gl.glVertex3fv(positions, indices[i]*3);
//			if (normals != null) {
//				gl.glVertex3f(
//					positions[indices[i]*3  ] + normals[indices[i]*3  ]*0.05f,
//					positions[indices[i]*3+1] + normals[indices[i]*3+1]*0.05f,
//					positions[indices[i]*3+2] + normals[indices[i]*3+2]*0.05f
//				);
//			}
//		}
//		gl.glEnd();
//		gl.glEnable(GL.GL_LIGHTING);
	}
	
	public BoundingBox getBoundingBox() {
		return boundingBox;
	}
	
	public void updateBoundingBox() {
		boundingBox.empty();
		if (vertexStream == null) {
			return;
		}
		
		FloatVertexAttrib posAttrib = (FloatVertexAttrib)vertexStream.getAttribByName("pos");
		if (posAttrib == null) {
			return;
		}
		
		float[] posBuf = posAttrib.getBuffer();
		if (posBuf == null) {
			return;
		}
		
		for(int i=0; i<posBuf.length; i+=3) {
			boundingBox.add(posBuf[i], posBuf[i+1], posBuf[i+2]);
		}
		
	}
	
}
