package org.helioviewer.gl3d.camera;

import java.awt.Point;
import java.awt.event.MouseEvent;

import org.helioviewer.gl3d.scenegraph.math.GL3DQuatd;
import org.helioviewer.gl3d.scenegraph.math.GL3DVec3d;
import org.helioviewer.gl3d.scenegraph.rt.GL3DRay;
import org.helioviewer.gl3d.scenegraph.rt.GL3DRayTracer;
import org.helioviewer.gl3d.view.GL3DSceneGraphView;
import org.helioviewer.jhv.display.Displayer;

/**
 * This interaction is used by the {@link GL3DTrackballCamera} as its rotation
 * interaction. The calculation of the rotation done by creating a rotation
 * Quaternion between two points on a sphere. These points are retrieved by
 * using the raycasting mechanism provided by {@link GL3DRayTracer}.
 * 
 * @author Simon Spoerri (simon.spoerri@fhnw.ch)
 * 
 */
public class GL3DTrackballRotationInteraction extends GL3DDefaultInteraction {
    private GL3DVec3d currentRotationStartPoint;
    private GL3DVec3d currentRotationEndPoint;
    private volatile GL3DQuatd currentDragRotation;

    protected GL3DTrackballRotationInteraction(GL3DSolarRotationTrackingTrackballCamera camera, GL3DSceneGraphView sceneGraph) {
        super(camera, sceneGraph);
    }

    @Override
    public void mouseDragged(MouseEvent e, GL3DCamera camera) {
        this.currentRotationEndPoint = getVectorFromSphere(e.getPoint(), camera);

        currentDragRotation = GL3DQuatd.calcRotation(currentRotationStartPoint, currentRotationEndPoint);
        camera.rotateCurrentDragRotation(currentDragRotation);
        this.camera.updateCameraTransformation(false);

        camera.fireCameraMoving();
        Displayer.getSingletonInstance().display();

    }

    @Override
    public void mouseReleased(MouseEvent e, GL3DCamera camera) {
        this.currentRotationStartPoint = null;
        this.currentRotationEndPoint = null;

        camera.fireCameraMoved();
        Displayer.getSingletonInstance().display();

    }

    @Override
    public void reset() {
        if (this.currentDragRotation != null) {
            this.currentDragRotation.clear();
        }
        super.reset();
    }

    @Override
    public void mousePressed(MouseEvent e, GL3DCamera camera) {
        // The start point of the rotation remains the same during a drag,
        // because the
        // mouse should always point to the same Point on the Surface of the
        // sphere.
        this.currentRotationStartPoint = getVectorFromSphere(e.getPoint(), camera);
    }

    protected GL3DVec3d getVectorFromSphere(Point p, GL3DCamera camera) {
        GL3DRayTracer sunTracer = new GL3DRayTracer(sceneGraphView.getHitReferenceShape(), camera);
        GL3DRay ray = sunTracer.cast(p.x, p.y);

        GL3DVec3d hitPoint;

        if (ray.isOnSun) {
            // Log.debug("GL3DTrackballRotationInteraction: Ray is Inside!");
            hitPoint = ray.getHitPoint();
            // System.out.println(hitPoint);
            hitPoint.normalize();
            hitPoint = camera.getLocalRotation().toMatrix().multiply(hitPoint);

        } else {
            // Log.debug("GL3DTrackballRotationInteraction: Ray is Outside!");
            double y = (camera.getHeight() / 2 - p.y) / camera.getHeight();
            double x = (p.x - camera.getWidth() / 2) / camera.getWidth();
            // Transform the Point so it lies on the plane that is aligned to
            // the viewspace (not the sphere)
            GL3DVec3d normalizedHelpVec = new GL3DVec3d(x, y, 0);
            normalizedHelpVec.normalize();
            hitPoint = normalizedHelpVec;
            // hitPoint =
            // camera.getRotation().toMatrix().multiply(normalizedHelpVec);
        }
        return hitPoint;
    }
}

@@ -2750,158 +2750,35 @@
     
-// Log.debug(%22GL3DTrackballRotationInteraction: Ray is Inside!%22);%0A            hitPoint = ray.getHitPoint();%0A            // System.out.println(hitPoint
+hitPoint = ray.getHitPoint(
 );%0A 
@@ -2802,32 +2802,33 @@
 nt.normalize();%0A
+%0A
             hitP
@@ -2891,25 +2891,28 @@
 Point);%0A
-%0A
+    
         
 %7D else %7B
@@ -2907,95 +2907,56 @@
     
-%7D else %7B%0A            // Log.debug(%22GL3DTrackballRotationInteraction: Ray is Outside!%22);
+double radeg = 180. / Math.PI;%0A%0A        %7D else %7B
 %0A   
@@ -3098,24 +3098,25 @@
 getWidth();%0A
+%0A
             
@@ -3119,119 +3119,424 @@
     
-// Transform the Point so it lies on the plane that is aligned to%0A            // the viewspace (not the sphere)
+GL3DVec3d nv = new GL3DVec3d(x, y, 0);%0A            nv.normalize();%0A            hitPoint = camera.getRotation().toMatrix().inverse().multiply(nv);%0A            hitPoint = camera.getLocalRotation().toMatrix().multiply(hitPoint);%0A            /*%0A             * //%0A             * Log.debug(%22GL3DTrackballRotationInteraction: Ray is Outside!%22);%0A             * System.out.println(ray.getOrigin() + %22 %22 + ray.getDirection());
 %0A   
@@ -3535,32 +3535,35 @@
 ());%0A           
+  *
  GL3DVec3d norma
@@ -3561,151 +3561,192 @@
 c3d 
-normalizedHelpVec = new GL3DVec3d(x, y, 0);%0A            normalizedHelpVec.normalize();%0A            hitPoint = normalizedHelpVec;%0A            //
+vec = ray.getDirection().copy();%0A             * vec.multiply(ray.getOrigin().length()); vec.add(ray.getOrigin());%0A             * vec.multiply(-1.); // vec.z = -Math.abs(vec.z) * vec.z;
  hit
@@ -3750,18 +3750,16 @@
 hitPoint
- =
 %0A       
@@ -3763,18 +3763,20 @@
         
-//
+ * =
  camera.
@@ -3770,32 +3770,37 @@
   * = camera.get
+Local
 Rotation().toMat
@@ -3818,27 +3818,88 @@
 ply(
-normalizedHelpVec);
+vec);%0A             * System.out.println(vec + %22HP %22 + hitPoint);%0A             */
 %0A   

fix rotation mode