package util;

import java.util.ArrayList;

public class SVGUtil extends SVGPrim {
	/* turtle graphics */
	protected static double __turtleX = 148.5, __turtleY = 105, __turtleHeading = 0;

	protected final static int UP = 0, CLEAN = 1, DIRTY = 2;

	protected static int __turtlePen = CLEAN;  /* up: 0, down: 1, dirty: 2 */
	protected static int __turtleFace = -1;

	protected static void adjustTurtle() {
		__turtleFace = __polyhedronNet.inWhichFace(new double[] {__turtleX, __turtleY}); 
		if (__turtleFace < 0) {
			__turtleFace = 0;
			double[] polygon = __polyhedronNet.get2DPolygons()[0];
			double[] center = Polyhedron.Net.faceCenter(polygon);
			__turtleX = center[0];  __turtleY = center[1];
		}
	}

	public static void setPolyhedronNet(Polyhedron.Net net) {
		SVGPrim.setPolyhedronNet(net);
		adjustTurtle();
	}

	public static void fitPolyhedronNet(double xmin, double ymin, double xmax, double ymax) {
		SVGPrim.fitPolyhedronNet(xmin, ymin, xmax, ymax);
		adjustTurtle();
	}

	public static void setRegularPolyhedronNet(int n) {
		SVGPrim.setRegularPolyhedronNet(n);
		adjustTurtle();
	}

	public static void penUp() {
		if (__turtlePen==DIRTY) {
			/*      endShape(false);  */
		}
		__turtlePen = UP;
	}
	
	public static void start() {
		SVGPrim.start();
		penDown();
	}
	
	public static void finish() {
		penUp();
		SVGPrim.finish();
	}

	public static void penDown() {
		if (__turtlePen==UP) {
			__turtlePen = CLEAN;        
		}
	}

	public static void forward(double len) {
		double dx = len * cos360(__turtleHeading);
		double dy = len * sin360(__turtleHeading);
		if (__turtlePen==CLEAN) {
			__turtlePen=DIRTY;
			//      beginShape();
			//      vertex(__turtleX, __turtleY);
		}

		double newX = __turtleX + dx, newY = __turtleY + dy;
		if (__polyhedronNet==null || __polyhedronNet.isInFace(new double[] { newX, newY }, __turtleFace)) {
			if (__turtlePen==DIRTY) {
				line(__turtleX, __turtleY, newX, newY);
			}
			__turtleX = newX; __turtleY = newY;
		} else {
			ArrayList<Triple<Integer, Double, double[]>> ret = __polyhedronNet.line(__turtleFace, new double[] { __turtleX, __turtleY }, new double[] { dx, dy} );
			for (Triple<Integer, Double, double[]> tmp : ret) {
				__turtleFace = tmp._1;
				__turtleHeading  += tmp._2/PI*180;
				double[] ln = tmp._3;
				if  (__turtlePen==DIRTY) {
					line(ln[0], ln[1], ln[2], ln[3]);
				}
				__turtleX = ln[2]; __turtleY = ln[3];
			}
		}
//		if (!__turtlePolyhedronNet.isInFace(new double[] { __turtleX, __turtleY  } , __turtleFace)) {
//			System.err.printf("<!-- forward (%f, %f) not in %d -->%n", __turtleX, __turtleY, __turtleFace);
//		}
		//      vertex(__turtleX + dx, __turtleY + dy);
	}

	public static void backward(double len) {
		double dx = - len * cos360(__turtleHeading);
		double dy = - len * sin360(__turtleHeading);
		__turtleX += dx;
		__turtleY += dy;
	}

	public static void turn(double angle) {
		__turtleHeading += angle;
		__turtleHeading %= 360;
		if (__turtleHeading < 0) {
			__turtleHeading += 360;
		}
	}

	public static void direction(double dir) {
		__turtleHeading = dir;
		__turtleHeading %= 360;
		if (__turtleHeading < 0) {
			__turtleHeading += 360;
		}
	}

	public static void go(double x, double y) {
		if (__turtleX!=x || __turtleY!=y) {
			if(__turtlePen==DIRTY) {
				penUp();
				__turtleX = x; __turtleY = y;
				penDown();
			} else {
				__turtleX = x; __turtleY = y;
			}
		}
	}

	public static void center() {
		go(148.5, 105);
	}

	public static double getX() {
		return __turtleX;
	}

	public static double getY() {
		return __turtleY;
	}

	public static double getAngle() {
		return __turtleHeading;
	}
}
