package modeler;

import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;

import net.java.games.jogl.GL;
import net.java.games.jogl.GLDrawable;

public class ScaleManip extends Manip {

  public ScaleManip(Transformation t) {

	  this.t = t;
  }

  Vector3f oWpos = new Vector3f();
  Vector3f xWpos = new Vector3f();
  Vector3f yWpos = new Vector3f();
  Vector3f zWpos = new Vector3f();
  public void dragged(Vector2f mousePosition, Vector2f mouseDelta) {
	Vector3f translation = new Vector3f();
	if (c instanceof OrthoCamera) {
	    switch (axisMode) {
	      case PICK_X:
	  		c.convertMotion(mouseDelta, translation);
	    	translation.y = translation.z = 0;
	    	t.S.sub(translation);
	        break;
	      case PICK_Y:
	  		c.convertMotion(mouseDelta, translation);
	    	translation.x = translation.z = 0;
		    t.S.sub(translation);
	        break;
	      case PICK_Z:
	  		c.convertMotion(mouseDelta, translation);
	    	translation.x = translation.y = 0;
		    t.S.sub(translation);
	        break;
	      case PICK_OTHER:
	    	Vector2f referenceDir = new Vector2f(mousePosition);
	    	referenceDir.sub(pickedMousePoint);
	        float s = referenceDir.dot(mouseDelta) / referenceDir.length() * c.getHeight();
	    	if (referenceDir.x < 0) s *= -1;
	        t.S.scale(1+s);
	        break;
	    }
	} else {
		// Perform a corrected computation for the perspective camera
		PerspectiveCamera pc = (PerspectiveCamera)c;
		t.toWorld(new Vector3f(2/t.S.x,0,0), xWpos);
		t.toWorld(new Vector3f(0,2/t.S.y,0), yWpos);
		t.toWorld(new Vector3f(0,0,2/t.S.z), zWpos);
		t.toWorld(new Vector3f(0,0,0), oWpos);
		Vector3f toManip = new Vector3f(oWpos);
	    toManip.sub(pc.getEye());
	    float dist = toManip.length();
	    
	    // use the gazeDirection-perpendicular plane height at the manipulator, not at the eye
	    float heightAtManip = (float)(Math.tan(Math.toRadians(pc.fovy/2.0)) * dist);
	    
	    Vector2f referenceDir = new Vector2f(mousePosition);
    	referenceDir.sub(pickedMousePoint);
    	float s;
    	if (referenceDir.length() == 0) {
    		s = 0;
    	} else {
    		s = referenceDir.dot(mouseDelta) / referenceDir.length() * heightAtManip;
    	}
    	
    	switch (axisMode) {
	      case PICK_X:
	    	xWpos.sub(oWpos);
	    	if (xWpos.dot(pc.right) < 0) s *= -1;
	    	if (referenceDir.x < 0) s *= -1;
	    	t.S.add(new Vector3f(s,0,0));
	        break;
	      case PICK_Y:
	    	yWpos.sub(oWpos);
	        //if (yWpos.dot(pc.up) < 0) s *= -1;
	        if (referenceDir.y < 0) s *= -1;
	    	t.S.add(new Vector3f(0,s,0));
	        break;
	      case PICK_Z:
	    	zWpos.sub(oWpos);
	        if (zWpos.dot(pc.right) < 0) s *= -1;
	        if (referenceDir.x < 0) s *= -1;
	    	t.S.add(new Vector3f(0,0,s));
	        break;
	      case PICK_OTHER:
	    	if (referenceDir.x < 0) s *= -1;
	        t.S.scale(1+s);
	        break;
	    }
	}

  }

  Vector3f skewX = new Vector3f();
  Vector3f skewY = new Vector3f();
  Vector3f skewZ = new Vector3f();
  public void glRender(GLDrawable d, double scale) {

    GL gl = d.getGL();
    gl.glPushAttrib(GL.GL_COLOR);

    gl.glPushAttrib(GL.GL_LIGHTING);
    gl.glDisable(GL.GL_LIGHTING);

    gl.glPushAttrib(GL.GL_DEPTH_TEST);
    gl.glDisable(GL.GL_DEPTH_TEST);

    gl.glPushMatrix();
    glDoLocation(gl, t);

    gl.glScaled(scale, scale, scale);

    normalizedSkewedAxes(gl, skewX, skewY, skewZ);
    
    gl.glPushMatrix();
	glRotateTo(gl,skewX);
    gl.glColor4d(0.8, 0, 0, 1);
    gl.glLoadName(PICK_X);
    glRenderBoxOnAStick(gl);
    gl.glPopMatrix();
    
    gl.glPushMatrix();
    glRotateTo(gl,skewY);
    gl.glColor4d(0, 0.8, 0, 1);
    gl.glLoadName(PICK_Y);
    glRenderBoxOnAStick(gl);
    gl.glPopMatrix();
    
    gl.glPushMatrix();
    glRotateTo(gl,skewZ);
    gl.glColor4d(0, 0, 0.8, 1);
    gl.glLoadName(PICK_Z);
    glRenderBoxOnAStick(gl);
    gl.glPopMatrix();    

    gl.glLoadName(PICK_OTHER);
    gl.glColor4d(0.8, 0.8, 0, 1);
    glRenderBox(gl);

    gl.glPopMatrix();

    gl.glPopAttrib();
    gl.glPopAttrib();
    gl.glPopAttrib();
  }

}