package math.geometry;

import java.util.ArrayList;

import math.equation.Polynomial;
import math.matrix.Vector;
import exception.ComplexException;
import exception.IllegalDimensionException;



/**
 * Work with quadrilateral / quadrangle / tetragon.
 * @author Daniel Weschke
 */
public class Tetragon extends Polygon {
	private static final int points = 4;
	
	/**
	 * Create empty tetragon.
	 */
	public Tetragon(){
		super(points);
	}
	
	/**
	 * Create tetragon by four points.
	 * @param a 1st point
	 * @param b 2nd point
	 * @param c 3rd point
	 * @param d 4th point
	 */
	public Tetragon(Point2D a, Point2D b, Point2D c, Point2D d){
		super(a, b, c, d);
	}
	
	/**
	 * Copy constructor
	 * @param a tetragon to copy
	 */
	public Tetragon(Tetragon a){
		this(a.get(0),a.get(1),a.get(2),a.get(3));
	}
	
	public Point2D intersection(){
		return intersection(false);
	}
	
	public Point2D intersection(boolean stepByStep){
		int i, ii;
		Point2D point = null;
		for(i=0; i<(points/2); i++){
			ii = (i+3)%4;
			if(point==null)
				point = intersection(get(i), i, get(i+1), i+1, get(i+2), i+2, get(ii), ii, stepByStep);
		}
		return point;
	}
	
	public static Point2D intersection(Point2D p1, int i1, Point2D p2, int i2, Point2D p3, int i3, Point2D p4, int i4, boolean stepByStep){
		double x1 = 0, x2 = 0;
		Polynomial f1 = null, f2 = null;
		Point2D point = null;
		if(p1.x() != p2.x()) f1 = line(p1, p2);
		else x1 = p1.x();
		if(p3.x() != p4.x()) f2 = line(p3, p4);
		else x2 = p3.x();
		if(f1!=null && f2!=null){
			if(stepByStep) System.out.println("f"+i1+""+i2+" = "+"f"+i3+""+i4+"\n => " + f1 + " = " + f2);
			try {
				Vector intersectionX = f1.solve(f2);
//					System.out.println(intersectionX);
				if(intersectionX != null){
					Vector intersectionY = f1.evaluate(intersectionX);
//						System.out.println(intersectionY);
					Point2D testPoint = new Point2D(intersectionX.get(0),intersectionY.get(0));
//						System.out.println(!contains(point));
//						System.out.println(pointInsideOuterRange(point));
					Tetragon tetragon = new Tetragon(p1,p2,p3,p4);
					if(!tetragon.contains(testPoint) && tetragon.pointInsideOuterRange(testPoint))
						point = testPoint;
				}
			} catch (ComplexException e) {
				e.printStackTrace();
			} catch (IllegalDimensionException e) {
				e.printStackTrace();
			}
		}
		else if(f1!=null){
			if(stepByStep) System.out.println("f"+i1+""+i2+"(x2)\n => f"+i1+""+2+"("+x2+") = " + f1);
			point = new Point2D(x2, f1.evaluate(x2));
		}
		else if(f2!=null){
			if(stepByStep) System.out.println("f"+i3+""+i4+"(x1)\n => f"+i3+""+i4+"("+x1+") = " + f2);
			point = new Point2D(x1, f2.evaluate(x1));
		}
		else{
			System.out.println("x1 = x2\n => " + x1 + " = " + x2);
		}
		if(stepByStep) System.out.println(" => " + point);
		return point;
	}
	
	public double area(){
		Point2D intersection = intersection(); 
		if(intersection==null) return new Polygon(this).area();
		else{
			ArrayList<Point2D> poly = new ArrayList<Point2D>(points+2);
			poly.add(0, get(0));
			Polynomial f1 = line(get(0), get(1));
			Polynomial f2 = line(get(2), get(3));
			try {
				Vector intersectionX = f1.solve(f2);
				if(intersectionX != null){
					poly.add(1, intersection);
					poly.add(2, get(2));
					poly.add(3, get(1));
					poly.add(4, intersection);
					poly.add(5, get(3));
				} else{
					poly.add(1, get(1));
					poly.add(2, intersection);
					poly.add(3, get(3));
					poly.add(4, get(2));
					poly.add(5, intersection);
				}
			} catch (ComplexException e) {
				e.printStackTrace();
			} catch (IllegalDimensionException e) {
				e.printStackTrace();
			}
//			System.out.println(new Polygon(poly));
			return new Polygon(poly).area();
		}
	}
	
    /**
     * test client
     * @param args
     */
    public static void main(String[] args) {
    	Tetragon t0 = new Tetragon(
    			new Point2D(0,1), new Point2D(1,1), new Point2D(2,2), new Point2D(1,2));
		System.out.println(t0.get());
    	System.out.println("A = " + t0.area());
    	System.out.println();
    	Tetragon t1 = new Tetragon(
    			new Point2D(0,1), new Point2D(1,1), new Point2D(0,2), new Point2D(1,2));
		System.out.println(t1.get());
    	System.out.println("A = " + t1.area());
//    	t1.intersection(true);
    }
}
