package CookieCutter.g5;

import java.util.*;
import java.awt.*;
import java.awt.geom.*;

public abstract class Corner extends Point2D.Double implements CookiePart {
	/*
	private Point2D.Double _prevPoint;
	private Point2D.Double _nextPoint;
	*/
	private Corner _prevPoint;
	private Corner _nextPoint;
	private boolean _used;
	private int _id;
	private int _owner;

	//public Corner( int id, Point2D.Double prev, Point2D.Double mid, Point2D.Double next ) {
	public Corner( int id, int owner, Corner prev, Point2D.Double mid, Corner next ) {
		super( mid.getX(), mid.getY() );
		_id = id;
		_owner = owner;
		_used = false;
		_prevPoint = prev;
		_nextPoint = next;
	}

	public int ID() {
		return( _id );
	}

	public int Owner() {
		return( _owner );
	}

	//public Point2D.Double prev() {
	public Corner prev() {
		return( _prevPoint );
	}

	//public void setPrev( Point2D.Double point ) {
	public void setPrev( Corner point ) {
		_prevPoint = point;
	}

	public double prevLength() {
		return( distance( prev() ) );
	}

	//public Point2D.Double next() {
	public Corner next() {
		return( _nextPoint );
	}

	//public void setNext( Point2D.Double point ) {
	public void setNext( Corner point ) {
		_nextPoint = point;
	}

	public boolean isUsed() {
		return( _used );
	}

	public void use() {
		_used = true;
	}

	public double nextLength() {
		return( distance( next() ) );
	}

	protected double _angle() throws Exception {
		double vec1[] = { _prevPoint.getX() - getX(), _prevPoint.getY() - getY() };
		double vec2[] = { _nextPoint.getX() - getX(), _nextPoint.getY() - getY() };
		double dp = VectorUtils.dotProduct( vec1, vec2 );
		dp /= ( VectorUtils.norm( vec1 ) * VectorUtils.norm( vec2 ) );
		return( Math.acos( dp ) );
	}

	public double angle() throws Exception {
		return( outerAngle() );
	}

	public Corner complement( Cookie cookie ) throws Exception {
		return( complement( cookie.getCorners() ) );
	}

	public double idealMeasure( Corner c ) throws Exception {
		//return( 2 * Math.PI - ( c.angle() + angle() ) ); 
		return( wastedArea( c ) );
	}

	/** Checks to see if the next() corner vertex corresponds to the next() 
	 * corner vertex of the other corner.  Also, true for prev() -> prev()
	 */
	public boolean correspondingVertices( Corner c ) {
		return( Line2D.Double.linesIntersect( prev().getX(), prev().getY(), 
			c.prev().getX(), c.prev().getY(), next().getX(), next().getY(), 
			c.next().getX(), c.next().getY() 
		) );
	}

	public double[] angleBisector() {
		double vec1[] = new double[2];
		vec1[0] = prev().getX() - getX();
		vec1[1] = prev().getY() - getY();
		vec1 = VectorUtils.normalize( vec1 );

		double vec2[] = new double[2];
		vec2[0] = next().getX() - getX();
		vec2[1] = next().getY() - getY();
		vec2 = VectorUtils.normalize( vec2 );

		double bisector[] = new double[2];
		bisector[0] = vec1[0] + vec2[0];
		bisector[1] = vec1[1] + vec2[1];

		return( VectorUtils.normalize( bisector ) );
	}

	public abstract double innerAngle() throws Exception;
	public abstract double outerAngle() throws Exception;
	public abstract double wastedArea( Corner corner ) throws Exception;
	public abstract Corner complement( Vector corners ) throws Exception;
}
