package jocode;


import java.awt.event.*;
import java.util.*;


/**
 * Change the position and orientation of a JOCamera based on input keys.  This
 * class moves the camera according to how much time has elapsed, so will 
 * produce consistent response to input, regardless of processor speed.
 * 
 * To use:
 * 
 * 
 * @see JOCamera.java
 */
public class JOCam implements KeyListener {

    // camera motion speed
    public float camSpeedR = 90;         // degrees per second
    public float camSpeedXZ = 10;        // units per second 
    public float camSpeedY  = 10;        // units per second

    public JOCamera camera;  // camera that we'll be moving

    public Hashtable<Integer, Boolean> keyPressed;

    double avgSecsPerFrame=.01;   // to smooth out motion, keep a moving average of frame time deltas
    double numToAvg = 50;         // number of frames to average (about one second)


    /**
     * Create a JOCam.  Will create a default camera.
     * 
     * @param cam
     */
    public JOCam() { 
        this(new JOCamera(0,0,10, 0,0,0, 0,1,0));
    }

    /**
     * Create a JOCam with the camera that it will be moving.
     * 
     * @param cam
     */
    public JOCam(JOCamera cam) {
        camera = cam;
        
        // 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);
        keyPressed.put(KeyEvent.VK_ALT, false);
        keyPressed.put(KeyEvent.VK_CONTROL, false);
        keyPressed.put(KeyEvent.VK_A, false);
        keyPressed.put(KeyEvent.VK_S, false);
        keyPressed.put(KeyEvent.VK_D, false);
        keyPressed.put(KeyEvent.VK_W, false);
        keyPressed.put(KeyEvent.VK_Z, false);
        keyPressed.put(KeyEvent.VK_C, false);
    }

    /**
     * Create a JOCam with the camera that it will be moving.
     * 
     * @param cam
     */
    public void setCamera(JOCamera cam) {
        camera = cam;
    }

    /**
     * Tell camera to adjust modelview matrix to new view position and orientation.
     *
     */
    public void render() {
         camera.render();
     }

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

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

     public void keyTyped(KeyEvent e) {}

     /**
      * Adjust the Camera position based on keyboard arrow key input.
      * These are repeating events (camera will move as long as key is held
      * down).  Moves the camera according to time elapsed, so camera motion
      * is consistent across varied cpu speeds.
      * 
      * @param seconds  seconds elapsed since last frame was drawn
      */
     public void handleNavKeys(float seconds) {
         //boolean altKeyDown = Keyboard.isKeyDown(Keyboard.KEY_RMENU)||Keyboard.isKeyDown(Keyboard.KEY_LMENU);
         //boolean ctrlKeyDown = Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)||Keyboard.isKeyDown(Keyboard.KEY_LCONTROL);

         // Basic motion
         handleArrowKeysOnly(seconds);

         // additional motion
         // Pan left
         if (keyPressed.get(KeyEvent.VK_A)) {
             camera.strafeRight(-camSpeedXZ*seconds);
         }
         // Pan right
         if (keyPressed.get(KeyEvent.VK_D)) {
             camera.strafeRight(camSpeedXZ*seconds);
         }
         // tilt down
         if (keyPressed.get(KeyEvent.VK_S)) {
             camera.rotateX(-camSpeedR*seconds);
         }
         // tilt up
         if (keyPressed.get(KeyEvent.VK_W)) {
             camera.rotateX(camSpeedR*seconds);
         }
         // tilt left
         if (keyPressed.get(KeyEvent.VK_Z)) {
             camera.rotateZ(camSpeedR*seconds);
         }
         // tilt right
         if (keyPressed.get(KeyEvent.VK_C)) {
             camera.rotateZ(-camSpeedR*seconds);
         }
     }

     /**
      * Adjust the Camera position based on keyboard arrow key input.
      * These are repeating events (camera will move as long as key is held
      * down).  Moves the camera according to time elapsed, so camera motion
      * is consistent across varied cpu speeds.
      * 
      * @param seconds  seconds elapsed since last frame was drawn
      */
     public void handleArrowKeysOnly(float seconds) {
         // Keep a moving average of recent frames, to smooth out jumps or lags in processing time
         //seconds = (float)updateAvgFrameTime(seconds);

         // Basic motion
         // Turn left
         if (keyPressed.get(KeyEvent.VK_LEFT)) {
             camera.rotateY(camSpeedR*seconds);
         }
         // Turn right
         if (keyPressed.get(KeyEvent.VK_RIGHT)) {
             camera.rotateY(-camSpeedR*seconds);
         }
         // move forward
         if (keyPressed.get(KeyEvent.VK_UP)) {
             camera.moveForward(-camSpeedXZ*seconds);
         }
         // move backward
         if (keyPressed.get(KeyEvent.VK_DOWN)) {
             camera.moveForward(camSpeedXZ*seconds);
         }
         // move down
         if (keyPressed.get(KeyEvent.VK_PAGE_UP)) {
             camera.moveUpward(camSpeedY*seconds);
         }
         // move up
         if (keyPressed.get(KeyEvent.VK_PAGE_DOWN)) {
             camera.moveUpward(-camSpeedY*seconds);
         }
     }

     /**
      * Adjust the Camera view direction based on key press events.  Do not 
      * change camera position.
      * 
      * @param seconds  seconds elapsed since last frame was drawn
      */
     public void handleNavKeysViewOnly(float seconds) {
         // Keep a moving average of recent frames, to smooth out jumps or lags in processing time
         avgSecsPerFrame = (double) ((avgSecsPerFrame*numToAvg)+seconds) / (numToAvg+1) ;
         seconds = (float)avgSecsPerFrame;

         //System.out.println("seconds elapsed = "+ seconds);

         // alt key combo
         if (keyPressed.get(KeyEvent.VK_ALT)) {
             // Pan left
             if (keyPressed.get(KeyEvent.VK_LEFT)) {
                 camera.rotateZ(camSpeedR*seconds);
             }
             // Pan right
             if (keyPressed.get(KeyEvent.VK_RIGHT)) {
                 camera.rotateZ(-camSpeedR*seconds);
             }
         }
         // control key combo
         else if (keyPressed.get(KeyEvent.VK_CONTROL)) {
             // tilt down
             if (keyPressed.get(KeyEvent.VK_UP)) {
                 camera.rotateX(-camSpeedR*seconds);
             }
             // tilt up
             if (keyPressed.get(KeyEvent.VK_DOWN)) {
                 camera.rotateX(camSpeedR*seconds);
             }
         }
         else {
             // Turn left
             if (keyPressed.get(KeyEvent.VK_LEFT)) {
                 camera.rotateY(camSpeedR*seconds);
             }
             // Turn right
             if (keyPressed.get(KeyEvent.VK_RIGHT)) {
                 camera.rotateY(-camSpeedR*seconds);
             }
         }
     }

}
