package demo;

import java.awt.event.*;
import java.util.*;
import javax.media.opengl.*;
import jocode.*;
import jomodel.*;

/**
 * Load and render an OBJ file.  Demonstrate simple navigation by moving the gluLookat()
 * viewpoint with the arrow keys.
 * <P>
 * Use GLModel to load the mesh and render it with texture and lighting.
 * <P>
 * GLApp initializes the LWJGL environment for OpenGL rendering,
 * ie. creates a window, sets the display mode, inits mouse and keyboard,
 * then runs a loop that calls draw().
 * <P>
 * napier at potatoland dot org
 */
public class DemoModel extends JOApp {
    // Model will be loaded from 3DS file
    JOModel object;
    JOImage sky;
    // Light direction: if last value is 0, then this describes light direction.  If 1, then light position.
    float lightDirection[]= { -2f, 2f, 2f, 0f };
    // Camera position
    static float[] cameraPos = { 0f, 4f, 35f };
    float cameraRotation = 0f;
    // A constant used in navigation
    final float piover180 = 0.0174532925f;

    float rotation = 0;
    
    Hashtable<Integer, Boolean> keyPressed;

	/**
	 * Start the application.  demo.run() calls setup(), handles mouse and keyboard input,
	 * and calls draw() in a loop.
	 */
    public static void main(String args[]) {
        DemoModel demo = new DemoModel();
        windowTitle   = "GLApp Demo Model";
        displayWidth  = 800;
        displayHeight = 600;
        demo.run();
    }
    
    public DemoModel() {
        super();
        
        // create and populate the keyPressed list
        keyPressed = new Hashtable<Integer, Boolean>();
        keyPressed.put(KeyEvent.VK_UP, false);
        keyPressed.put(KeyEvent.VK_DOWN, false);
        keyPressed.put(KeyEvent.VK_LEFT, false);
        keyPressed.put(KeyEvent.VK_RIGHT, false);
        keyPressed.put(KeyEvent.VK_PAGE_UP, false);
        keyPressed.put(KeyEvent.VK_PAGE_DOWN, false);
    }

    /**
     * Initialize the scene.  Called by JOApp.run()
     */
    @Override
    public void setup() {
        // enable lighting and texture rendering
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_TEXTURE_2D);

        gl.glClearColor(.5f,.6f,.9f,1f);

        // setup and enable perspective
        setPerspective();

        // Create a light
        setLight(GL.GL_LIGHT1,
        		 new float[] { 1f,  1f,  1f,  1f },    // diffuse color
        		 new float[] { .6f, .6f, .9f, 1f },    // ambient
        		 new float[] { 1f,  1f,  1f,  1f },    // specular
        		 lightDirection );                     // direction/position

        setAmbientLight(new float[] { .6f, .6f, .9f, 1f });

        sky = loadImage("images/sky.jpg");

        // Load the model
        object = new JOModel("models/JetFire/JetFire.obj");
        object.regenerateNormals();
    }

    /**
     * Render one frame.  Called by GLApp.run().
     */
    @Override
    public void render() {
    	// use the frames per second to animate
    	rotation += 25f * getSecondsPerFrame();

        // clear depth buffer and color
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // draw background image 
    	drawImageFullScreen(sky);

        // adjust camera position according to arrow key events
        setCameraPosition();

        // select model view and reset
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        // set the viewpoint
        glu.gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2], // where is the eye
					 // look at a point directly in front of camera
					 cameraPos[0]-(float)Math.sin(cameraRotation* piover180), cameraPos[1], cameraPos[2]- (float) Math.cos(cameraRotation* piover180),
        			 0f, 1f, 0f);   // which way is up

        // draw object at center
        gl.glPushMatrix();
        {
            gl.glRotatef(rotation, 0, 1, 0);  // turn it
            gl.glScalef(20f,20f,20f);
            object.render();
        }
        gl.glPopMatrix();

        // Place the light.  Light will move with the rest of the scene
        setLightPosition(GL.GL_LIGHT1, lightDirection);
    }

    /**
     * set the field of view and view depth.
     */
    public void setPerspective() {
    	setPerspective(40f, .1f, 500f);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        super.keyPressed(e);
        keyPressed.put(e.getKeyCode(), true);
    }

    @Override
    public void keyReleased(KeyEvent e) {
        super.keyReleased(e);
        keyPressed.put(e.getKeyCode(), false);
    }

    /**
     * Adjust the Camera position based on keyboard arrow key input.
     */
    public void setCameraPosition() {
        // Turn left
        if (keyPressed.get(KeyEvent.VK_LEFT)) {
            cameraRotation += 1.0f;
        }
        // Turn right
        if (keyPressed.get(KeyEvent.VK_RIGHT)) {
            cameraRotation -= 1.0f;
        }
        // move forward in current direction
        if (keyPressed.get(KeyEvent.VK_UP)) {
            cameraPos[0] -= (float) Math.sin(cameraRotation * piover180) * .3f;
            cameraPos[2] -= (float) Math.cos(cameraRotation * piover180) * .3f;
        }
        // move backward in current direction
        if (keyPressed.get(KeyEvent.VK_DOWN)) {
            cameraPos[0] += (float) Math.sin(cameraRotation * piover180) * .3f;
            cameraPos[2] += (float) Math.cos(cameraRotation * piover180) * .3f;
        }
        // move camera down
        if (keyPressed.get(KeyEvent.VK_PAGE_UP)) {
            cameraPos[1] +=  .13f;
        }
        // move camera up
        if (keyPressed.get(KeyEvent.VK_PAGE_DOWN)) {
            cameraPos[1] -=  .13f;
        }
    }
}