package psplot;

import java.awt.Color;
import real.*;

public class MovableLine implements mouseActive {
	// Ax + By + C = 0
	double coeff[];
	double epsilon;
	PlotCanvas canvas;
	public Color fillColor = Color.black;
	RealPolygon boundary;
	public RealPoint pivot;
	
	public MovableLine(PlotCanvas c, double A, double B, RealPoint Q, double e) {
		canvas = c;
		coeff = new double[3];
		epsilon = e;
		pivot = Q;
		double C = A*Q.x + B*Q.y;
		setCoeffs(A, B, C);
	}
	
	public MovableLine(PlotCanvas c, RealPoint P, RealPoint Q, double e) {
		canvas = c;
		coeff = new double[3];
		pivot = P;
		double A = -(P.y - Q.y); double B = P.x - Q.x;
		double C = A*P.x + B*P.y;
		epsilon = e;
		setCoeffs(A, B, C);
	}
	
	public void setFillColor(Color c) {
		fillColor = c;
	}
	
	public void setCoeffs(double A, double B, double C) {
		coeff[0] = A;
		coeff[1] = B;
		coeff[2] = C;
	}
	
	public double evaluate(RealPoint P) {
		return(coeff[0]*P.x + coeff[1]*P.y + coeff[2]);
	}
	
	// -------------------------------------------------------------
	
	// returns [A, B] rotated 90 degrees
	public Real2DVector direction() {
		return(new Real2DVector(-coeff[1], coeff[0]));
	}
	
	public RealPoint intersection(double A, double B, double C) {
		double x, y;
		x = (coeff[1]*C - B*coeff[2])/(coeff[1]*A - B*coeff[0]);
		y = (coeff[0]*C - A*coeff[2])/(coeff[0]*B - A*coeff[1]);
		
		return(new RealPoint(x, y));
	}
	
	// -------------------------------------------------------------
	
	public int active = -1;
	Real2DVector a;
	
	public boolean mouseDown(RealPoint P, int flag) {
		if (mouseDown(P) && (active & flag) != 0) {
			return(true);
		} else return(false);
	}
	
	// rp = null, active = -1 on entry
	public boolean mouseDown(RealPoint P) {
		double X = evaluate(P);
		if (Math.abs(X) < epsilon) {
			active = 0;
			return(true);
		}
		return(false);
	}
	
	public boolean mouseDrag(RealPoint P) {
		switch(active) {
			case 0:
				// pivot = origin
				if (Math.abs(P.x) + Math.abs(P.y) > epsilon) {
					coeff[0] = -P.y + pivot.y;
					coeff[1] = P.x - pivot.x;
					coeff[2] = coeff[0]*pivot.x + coeff[1]*pivot.y;
					return(true);
				}
				break;
			default:
				break;
		}
		return(false);
	}
	
	public boolean mouseUp(RealPoint P) {
		if (active > -1) {
			switch(active) {
				default:
					break;
			}
			active = -1;
			return(true);
		}
		return(false);
	}
	
	public RealPoint[] visibleEnds() {
		RealPoint E[] = new RealPoint[2];
		boundary = canvas.vertexBoundary();
		boolean started = false;
		// draw the line from one side of the boundary to the other
		RealPoint P = boundary.b[3];
		double cP = evaluate(P);
		for (int i=0;i<4;i++) {
			RealPoint Q = boundary.b[i];
			double cQ = evaluate(Q);
			// if P in and Q ouit, interpolate to get R
			if (cP <= 0 && cQ > 0) {
				double t = (-cP)/(cQ - cP);
				double x = t*Q.x + (1 - t)*P.x;
				double y = t*Q.y + (1 - t)*P.y;
				if (started) {
					E[1] = new RealPoint(x, y);
					break;
				} else {
					started = true;
					E[0] = new RealPoint(x, y);
				}
			} else if (cP > 0 && cQ <= 0) {
				double t = (-cQ)/(cP - cQ);
				double x = t*P.x + (1 - t)*Q.x;
				double y = t*P.y + (1 - t)*Q.y;
				if (started) {
					E[1] = new RealPoint(x, y);
					break;
				} else {
					started = true;
					E[0] = new RealPoint(x, y);
				}
			}
			cP = cQ;
			P = Q;
		}
		return(E);
	}
	
	public String toString() {
		return("<" + Real.toString(coeff[0], 4, 8) 
			+ ": " + Real.toString(coeff[1], 4, 8) + ": " 
			+ Real.toString(coeff[2], 4, 8) + ">");
	}
} 