package psplot;

import java.awt.*;

import real.*;
import psplot.*;

/** PlotPaths are the basic class drawn into PlotCanvases.
	Drawing follows the PostScript model.
	Each path is an array of segments.
	Each segment is an array of coordinates.
	Stroking a path means drawing lines along the pieces.
	Filling it means turning each piece into a polygon. */
   
   // Design exceptions to recover from: no current point etc.
   
public class PlotPath {
	final static int INC = 128;

	PlotCanvas canvas;
	Graphics gfx;
	Color colour = Color.black;

	PathSegment segment[];
	PathSegment currentSegment = null;
	int maxSegmentNo = INC;
	int segmentNo;
	
	// mark last move:
	int lastx, lasty;
	RealPoint CurrentPoint;
	int N = 0;

	public PlotPath(PlotCanvas can) {
		canvas = can;
		gfx = canvas.gfx;
		segment = new PathSegment[INC];
		segmentNo = 0;
	}

	public PlotPath(PlotCanvas can, Graphics g) {
		canvas = can;
		gfx = g;
		segment = new PathSegment[INC];
		segmentNo = 0;
	}

	public PlotPath(PlotCanvas can, Color col) {
		canvas = can;
		colour = col;
		segment = new PathSegment[INC];
		segmentNo = 0;
	}

	public void setColor(Color c) {
		colour = c;
	}

	RealPoint currentPoint() {
		return(CurrentPoint);
	}

	// - moves --------------------------------------------

	public void moveto(double x, double y) {
		if (segmentNo >= maxSegmentNo) {
			// System.out.println("overflow!");
			maxSegmentNo += INC;
			PathSegment newseg[] = new PathSegment[maxSegmentNo];
			for (int i=0;i<segmentNo;i++) {
				newseg[i] = segment[i];
			}
			newseg[segmentNo++] = new PathSegment();
			segment = newseg;
		}
		segment[segmentNo] = new PathSegment();
		currentSegment = segment[segmentNo++];
		Point q = canvas.toPoint(x, y);
		currentSegment.add(q);
		lastx = q.x; lasty = q.y;
		CurrentPoint = new RealPoint(x, y);
	}

	public void moveto(RealPoint p) {
		moveto(p.x, p.y);
	}
	
	public void rmoveto(Real2DVector p) {
		double cx = CurrentPoint.x + p.x;
		double cy = CurrentPoint.y + p.y;
		moveto(cx, cy);
	}

	public void rmoveto(double x, double y) {
		double cx = CurrentPoint.x + x;
		double cy = CurrentPoint.y + y;
		moveto(cx, cy);
	}

	// - lines --------------------------------------------

	public void lineto(RealPoint p) {
		N++;
		Point q = canvas.toPoint(p);
		currentSegment.add(q);
		CurrentPoint.x = p.x;
		CurrentPoint.y = p.y;
	}
	
	public void lineto(double x, double y) {
		Point q = canvas.toPoint(x, y);
		N++;
		// System.out.println("lineto: q = " + q);
		currentSegment.add(q);
		CurrentPoint.x = x;
		CurrentPoint.y = y;
	}

	public void rlineto(Real2DVector p) {
		CurrentPoint.x += p.x;
		CurrentPoint.y += p.y;
		N++;
		Point q = canvas.toPoint(CurrentPoint);
		currentSegment.add(q);
	}

	public void rlineto(double x, double y) {
		CurrentPoint.x += x;
		CurrentPoint.y += y;
		Point q = canvas.toPoint(CurrentPoint);
		N++;
		// System.out.println("lineto: q = " + q);
		currentSegment.add(q);
	}

	// - curves -------------------------------------------
	
	public void curveto(RealPoint P1, RealPoint P2, RealPoint P3) {
		P1 = canvas.toFinePoint(P1);
		P2 = canvas.toFinePoint(P2);
		P3 = canvas.toFinePoint(P3);
		curve.addCurve(currentSegment, P1, P2, P3);
	}

	// ----------------------------------------------------
	
	public void add(PathSegment ps) {
		if (segmentNo >= maxSegmentNo) {
			// System.out.println("overflow!");
			maxSegmentNo += INC;
			PathSegment newseg[] = new PathSegment[maxSegmentNo];
			for (int i=0;i<segmentNo;i++) {
				newseg[i] = segment[i];
			}
			newseg[segmentNo++] = new PathSegment();
			segment = newseg;
		}
		segment[segmentNo] = ps;
		currentSegment = segment[segmentNo++];
	}
	
	public void add(PlotPath p) {
		if (p.segmentNo > 0) {
			currentSegment.add(p.segment[0]);
		}
		if (p.segmentNo > 1) {
			for (int i=1;i<p.segmentNo;i++) {
				add(p.segment[i]);
			}
		}
	}
	
	public void close() {
		currentSegment.add(lastx, lasty);
		// closed = true;
		moveto(lastx, lasty);
	}

	// all routines drawing a polygon return the polygon!
	// unlike PostScript - does not destroy the path
	// but we should close off graphics to it ...

	public void stroke() {
		stroke(colour);
	}

	public void stroke(Color c) {
		Color tmp = gfx.getColor();
		gfx.setColor(c);
		for (int i=0;i<segmentNo;i++) {
			PathSegment p = segment[i];
			p.draw(gfx);
		}
		gfx.setColor(tmp);
	}

	public void fill() {
		// close path first?
		fill(colour);
	}

	public void fill(Color c) {
		// closepath first?
		Color tmp = gfx.getColor();
		gfx.setColor(c);
		for (int i=0;i<segmentNo;i++) {
			Polygon p = segment[i].toPolygon();
			gfx.fillPolygon(p);
		}
		gfx.setColor(tmp);
	}

	void print() {
		for (int i=0;i<segmentNo;i++) {
			segment[i].print();
			System.out.println(":");
		}
	}
}

