package plot;

import java.awt.*;
import java.util.Stack;
import real.Formats;

// -- PathConstructor -----------------------------------------


class PathConstructor implements ActivePath {
	final static int Quiet = 0, 
		Move = 1, Line = 2, Curve = 3;
	int state;
	// double last[];
	double currentPoint[];
	
	Stack segmentStack;
	RealGraphics gfx;
	
	public PathConstructor(RealGraphics gfx) {
		segmentStack = new Stack();
		state = Quiet;
		this.gfx = gfx;
		current = null;
	}
	
	double[] last() {
		PathSegment seg;
		for (int i=segmentStack.size();i>0;i--) {
			 seg = (PathSegment) segmentStack.elementAt(i-1);
			if (seg instanceof MovetoSegment) {
				MovetoSegment m = (MovetoSegment) seg;
				return(m.x);
			}
		}
		return(null);
	}
	
	public void setState(int s) {
		state = s;
	}
	
	int n = 0;
	final static int M = 3;
	public void addSegment(double p[]) throws NoCurrentPointException {
		int n = segmentStack.size();
		switch(state) {
			case Move: {
				currentPoint = p;
				moveto(p);
				break;
			}
			case Line: {
				lineto(p);
				currentPoint = p;
				break;
			}
			case Curve: {
				double q[][] = new double[3][];
				q[0] = new double[2];
				q[0][0] = (2*currentPoint[0] + p[0])/3;
				q[0][1] = (2*currentPoint[1] + p[1])/3;
				q[1] = new double[2];
				q[1][0] = (currentPoint[0] + 2*p[0])/3;
				q[1][1] = (currentPoint[1] + 2*p[1])/3;
				q[2] = p;
				curveto(q);
				currentPoint = p;
				break;
			}
		}
	}
	
	public int size() {
		return(segmentStack.size());
	}
	
	public void pop() {
		if (segmentStack.size() > 0) segmentStack.pop();
	}
	
	// -------------------------------------------
	
	double current[];
	void moveto(double x[]) {
		PathSegment ds = new MovetoSegment(gfx, x);
		current = x;
		segmentStack.push(ds);
	}
	
	void lineto(double x[]) throws NoCurrentPointException {
		if (current != null) {
			PathSegment ds = new LinetoSegment(gfx, x);
			current = x;
			segmentStack.push(ds);
		} else {
			throw(new NoCurrentPointException()); 
		}
	}
	
	void curveto(double x[][]) throws NoCurrentPointException {
		if (current != null) {
			PathSegment ds = new CurvetoSegment(gfx, x, current);
			current = x[2];
			segmentStack.push(ds);
		} else {
			throw(new NoCurrentPointException()); 
		}
	}
	void close() {
		PathSegment ds = new CloseSegment(gfx);
		current = last();
		segmentStack.push(ds);
	}
	
	// ---------------------------------------------
	
	public void draw(RealGraphics gfx) {
		PlotPath p = new PlotPath(gfx);
		for (int i=0;i<segmentStack.size();i++) {
			PathSegment s = (PathSegment) segmentStack.elementAt(i);
			s.addTo(p);
			s.draw();
		}
		p.stroke(Color.gray);
	}
	
	public void setActive(boolean a) {
		for (int i=0;i<segmentStack.size();i++) {
			PathSegment s = (PathSegment) segmentStack.elementAt(i);
			s.setActive(a);
		}
	}
	
	public Object mouseDown(double x[]) {
		Object active = null;
		for (int i=0;i<segmentStack.size();i++) {
			PathSegment s = (PathSegment) segmentStack.elementAt(i);
			Object y = s.mouseDown(x);
			if (y != null) active = y;
		}
		return(active);
	}
	public Object mouseDrag(double x[]) {
		return(null);
	}
	public Object mouseUp(double x[]) {
		return(null);
	}
}
