package cz.fidentis.analyst.canvas;

import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import cz.fidentis.analyst.scene.Camera;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Animates rotation and zooming of the camera in GLCanvas 
 * when pressing and holding manipulation button in the canvas.
 * 
 * @author Natalia Bebjakova 
 * @author Radek Oslejsek
 */
public class RotationAnimator {
    
    /**
     * Frequency of the rotation or zoom animations
     */
    private static final int FPS = 60; 
    
    /**
     * Animator used when the rotation or zoom buttons are pressed and held
     */
    private final FPSAnimator animator;
    
    /*
     * Animatio timer
     */
    private long startClickTime = 0;
    private TimerTask task;
    private Timer timer;
    
    private Direction direction = Direction.NONE;
    
    /**
     * Constructor.
     * 
     * @param glCanvas OpenGL canvas
     * @throws IllegalArgumentException if some argument is missing
     */
    public RotationAnimator(GLCanvas glCanvas) {
        if (glCanvas == null) {
            throw new IllegalArgumentException("glCanvas is null");
        }
        //if (camera == null) {
        //    throw new IllegalArgumentException("camera is null");
        //}
        //this.camera = camera;
        this.animator = new FPSAnimator(glCanvas, FPS, true);
    }
    
    /**
     * Starts the animation.
     * 
     * @param dir Animation direction
     * @throws UnsupportedOperationException if there is unfinished animation
     */
    public void startAnimation(Direction dir, Camera camera) {
        if (this.direction != Direction.NONE) {
            throw new UnsupportedOperationException(); // this should no happen
        }
        
        animator.start();
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                switch (dir) {
                    case ROTATE_LEFT:
                        camera.rotateLeft(2);
                        break;
                    case ROTATE_RIGHT:
                        camera.rotateRight(2);
                        break;
                    case ROTATE_UP:
                        camera.rotateUp(2);
                        break;
                    case ROTATE_DOWN:
                        camera.rotateDown(2);
                        break;
                    case ZOOM_IN:
                        camera.zoomIn(3);
                        break;
                    case ZOOM_OUT:
                        camera.zoomOut(3);
                        break;
                    default:
                        throw new UnsupportedOperationException();
                }
            }
        };
        timer.schedule(task, 500, 100);
        
        this.direction = dir;        
    }
    
    /**
     * Stops the animation.
     */
    public void stopAnimation(Camera camera) {
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            switch (direction) {
                case ROTATE_RIGHT:
                    camera.rotateRight(22.5);
                    break;
                case ROTATE_LEFT:
                    camera.rotateLeft(22.5);
                    break;
                case ROTATE_UP:
                    camera.rotateUp(22.5);
                    break;
                case ROTATE_DOWN:
                    camera.rotateDown(22.5);
                    break;
                case ZOOM_IN:
                    camera.zoomIn(30);
                    break;
                case ZOOM_OUT:
                    camera.zoomOut(30);
                    break;
                default:
                    throw new UnsupportedOperationException();
            }
        }
        startClickTime = 0;
        animator.stop();
        this.direction = Direction.NONE;
    }
}
