package sytar.opengl;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import sytar.processing.BitMap;

import com.jogamp.opengl.util.texture.Texture;

/**
 * @author ABA
 * 
 */
public class Renderer implements GLEventListener {

	class Point {
		private static final int	MAX_LIFE		= 100;
		float[]						coords			= new float[3];
		int							intensity;
		int							life			= MAX_LIFE;
	}
	private static final int	IMG_SIZE		= 500;
	private static final float	MOTION_FACTOR	= 0.1f;
	private static final float	ZOOM_FACTOR		= 1.1f;
	private BitMap				bitMap;
	private GL2					gl;
	private Texture				texture;
	private float				x_rot, y_rot, z_rot;
	private float				zoom, x_offset, y_offset;

	/**
	 * Constructor
	 */
	public Renderer () {
		bitMap = new BitMap(IMG_SIZE, IMG_SIZE);
	}

	@Override
	public void init (GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();
		bitMap.setGL(drawable);

		gl.glShadeModel(GL2.GL_SMOOTH);
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black background
		gl.glClearDepth(1.0f);
		gl.glEnable(GL2.GL_BLEND);
		gl.glEnable(GL2.GL_TEXTURE_2D);
		gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
		gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE);

		gl.glColorMaterial(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE);
		gl.glColor3f(1.0f, 1.0f, 1.0f);
		gl.glEnable(GL2.GL_COLOR_MATERIAL);
		
		gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
		gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
		gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);

		resetView();
	}
	
	/**
	 * Simple method which reset the view of the 'map'
	 */
	private void resetView () {
		zoom = -15.0f;
		x_offset = 0.0f;
		y_offset = 0.0f;
		x_rot = 0.0f;
		y_rot = 0.0f;
		z_rot = 0.0f;
	}

	/**
	 * Read a file and return its content in a String object
	 * 
	 * @param filePath file path of the file you would like to read
	 * @return a string with the content of the file
	 * @throws java.io.IOException if the file does not exist
	 */
	public static String readFileAsString (String filePath) throws java.io.IOException {
		byte[] buffer = new byte[(int) new File(filePath).length()];
		BufferedInputStream f = null;
		try {
			f = new BufferedInputStream(new FileInputStream(filePath));
			f.read(buffer);
		} finally {
			if (f != null)
				try {
					f.close();
				} catch (IOException ignored) {
					System.out.println(ignored.getMessage());
				}
		}
		return new String(buffer);
	}
	
	
	@Override
	public void display (GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();

		gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		gl.glLoadIdentity();
		gl.glTranslatef(x_offset, y_offset, zoom);
		gl.glPushMatrix();
		gl.glRotatef(y_rot, 1.0f, 0.0f, 0.0f);
		gl.glRotatef(x_rot, 0.0f, 1.0f, 0.0f);
		gl.glRotatef(z_rot, 0.0f, 0.0f, 1.0f);
		
		gl.glFinish();
		texture = bitMap.getTexture();
		texture.bind();
		
		gl.glBegin(GL2.GL_QUADS);
		
		gl.glNormal3f(0.0f, 0.0f, 1.0f);
		gl.glTexCoord2f(0.0f, 0.0f);
		gl.glVertex3f(5.0f, -5.0f, 0.0f);
		gl.glTexCoord2f(0.0f, 1.0f);
		gl.glVertex3f(5.0f, 5.0f, 0.0f);
		gl.glTexCoord2f(1.0f, 1.0f);
		gl.glVertex3f(-5.0f, 5.0f, 0.0f);
		gl.glTexCoord2f(1.0f, 0.0f);
		gl.glVertex3f(-5.0f, -5.0f, 0.0f);

		gl.glEnd();
		gl.glPopMatrix();
		gl.glFlush();
	}

	/**
	 * @param drawable the {@link GLAutoDrawable} object
	 */
	public void dispose (GLAutoDrawable drawable) {
		System.err.println("Dispose OpenGL object.");
		bitMap.save("tmp.png");
	}

	@Override
	public void reshape (GLAutoDrawable drawable, int x, int y, int width, int height) {
		gl = drawable.getGL().getGL2();

		final GLU glu = new GLU();

		if (height <= 0) // avoid a divide by zero error!
			height = 1;
		final float h = (float) width / (float) height;
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(45.0f, h, 0.0, 1000.0);
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glLoadIdentity();
	}

}