package rotation;

import java.applet.*;
import java.awt.*;
import psplot.*;
import real.*;

class rotation2AppletCanvas extends PlotCanvas {
	PlotNode cn[];
	double x, y;
	double a;
	double R, d = 0.40;
	Font ell;
	double labelW = 0.42, labelH = 0.16;
	
	public rotation2AppletCanvas(Applet app, int w, int h, 
				double x, double y, double a) {
		super(app, w, h);
		this.x = x;
		this.y = y;
		this.a = a;
		R = Math.sqrt(x*x + y*y);
		double W = R+2, H = W*h/w;
		setCorners(-W, -H, W, H);
		RealPoint P = new RealPoint(x, y);
		Font ell = new Font("Times-Oblique", Font.ITALIC, 14);
		setFont(ell);
		cn = new PlotNode[2];
		cn[0] = new PlotNode(this, P);
		P = P.rotated(a);
		cn[1] = new PlotNode(this, P);
		mkFixedpaths();
		repaint();
	}
	
	PlotPath circle;
	PlotPath triangle0;
	PlotPath triangle1;
	PlotPath triangle2;
	PlotPath triangle3;
	
	void mkFixedpaths() {
		circle = new PlotPath(this);
		int N = 64;
		double A = 0.0;
		double inc = Math.PI*2.0/N;
		circle.moveto(R, 0);
		for (int i=0;i<N;i++) {
			A += inc;
			circle.lineto(R*Math.cos(A), R*Math.sin(A));
		}
		circle.close();
	}
	
	boolean ready = true;
	
	public void draw() {
		ready = false;
		circle.fill(Color.white);
		circle.stroke(Color.black);
		
		double c = Math.cos(a);
		double s = Math.sin(a);
		
		triangle2 = new PlotPath(this);
		triangle2.moveto(0, 0);
		triangle2.lineto(c*x, c*y);
		triangle2.lineto(c*x - s*y, s*x + c*y);
		triangle2.close();
		triangle2.fill(Color.lightGray);
		triangle2.stroke(Color.black);
		
		triangle0 = new PlotPath(this);
		
		triangle0.moveto(0, 0);
		triangle0.lineto(x, 0);
		triangle0.lineto(x, y);
		triangle0.close();
		triangle0.fill(Color.red);
		triangle0.stroke(Color.black);
		
		triangle1 = new PlotPath(this);
		triangle1.moveto(0, 0);
		triangle1.lineto(c*x, 0);
		triangle1.lineto(c*x, c*y);
		triangle1.close();
		triangle1.fill(Color.pink);
		triangle1.stroke(Color.black);
		
		triangle3 = new PlotPath(this);
		triangle3.moveto(c*x, c*y);
		triangle3.lineto(c*x - s*y, c*y);
		triangle3.lineto(c*x - s*y, s*x + c*y);
		triangle3.close();
		triangle3.fill(Color.magenta);
		triangle3.stroke(Color.black);
				
		cn[0].draw();
		cn[1].draw();
		
		double xL, yL;
		xL = x*(R + d)/R;
		yL = y*(R+d)/R;
		drawString("( x, y )", xL - 0.5*labelW, yL - 0.5*labelH);
		drawString("( x', y' )", xL*c - yL*s - 0.5*labelW, xL*s + yL*c - 0.5*labelH);
		ready = true;
	}
	
	int active = -1;

	public boolean mouseDown(Event evt, int x, int y) {
		// if (x, y) inside a node set mouseState = MouseActive
		RealPoint P = toRealPoint(x, y);
		for (int i=1;i >= 0;i--) {
			if (cn[i].contains(P)) {
				if (i == 0) {
					PlotNode pn = cn[0];
					cn[0] = cn[1];
					cn[1] = pn;
				}
				active = i;
				return(true);
			}
		}
		return true;
	}

	public boolean mouseDrag(Event evt, int x, int y) {
		if (active > -1 && ready) {
			switch (active) {
			case 0: {
				// move (x, y);
				RealPoint q = toRealPoint(x, y);
				q.normalize(R);
				// System.out.println(q);
				cn[0].locate(q);
				this.x = q.x; this.y = q.y;
				q = q.rotated(a);
				cn[1].locate(q);
				repaint();
				break;
			}
			
			case 1: {
				// change alpha
				RealPoint q = toRealPoint(x, y);
				q.normalize(R);
				// System.out.println(q);
				cn[1].locate(q);
				a = Math.atan2(q.y, q.x) - Math.atan2(this.y, this.x);
				repaint();
				break;
			}
			
			default: {
			
				break;
			}
			}
		}
		return true;
	}

	public boolean mouseUp(Event evt, int x, int y) {
		// set nodes inactive
		active = -1;
		return true;
	}
}

public class rotation2Applet extends Applet {

	rotation2AppletCanvas baby;
	double x = 1.4*Math.cos(Math.PI/6.0);
	double y = 1.4*Math.sin(Math.PI/6.0);
	
	public void init() {
		setBackground(Color.white);
		baby = new rotation2AppletCanvas(this, bounds().width, bounds().height,
			x, y, Math.PI/5.0);
		add(baby);
		show();
	}

}