package shapeUtil;

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

class AlignedCouple{
    protected Align targetAlign=null;
    protected Align hitAlign=null;
    protected Point2D targetAlignPoint=null;
    protected Point2D hitAlignPoint=null;
	int debug=0;
	public static double ErrorMax=1.0d+5;
    
    public AlignedCouple(Align targetAlign, Align hitAlign){
        this.targetAlign=targetAlign;
        this.hitAlign=hitAlign;
        this.setAlignPoints();
    }
    
    private void setAlignPoints(){
        int alignAxis=this.hitAlign.getAlignAxis();
        Point2D[] targetAlignPTs=this.targetAlign.getAlignedPoints();
        Point2D[] hitAlignPTs=this.hitAlign.getAlignedPoints();
        Point2D targetAlignPT=null;
        Point2D hitAlignPT=null;
        double distMin=1.0e+5;
        for(int j=0;j<targetAlignPTs.length;j++){
            for(int i=0;i<hitAlignPTs.length;i++){
                double dist=1.0e+5;
                if(alignAxis==Align.XALIGN) dist=Math.abs(targetAlignPTs[j].getY()-hitAlignPTs[i].getY());
                if(alignAxis==Align.YALIGN) dist=Math.abs(targetAlignPTs[j].getX()-hitAlignPTs[i].getX());
                if(dist<distMin) {
                    distMin=dist;
                    targetAlignPT=targetAlignPTs[j];
                    hitAlignPT=hitAlignPTs[i];
                }
            }
        }
        this.targetAlignPoint=targetAlignPT;
        this.hitAlignPoint=hitAlignPT;
    }

    public Point2D getTargetAlignPoint(){
        return this.targetAlignPoint;
    }
    
    public Point2D getHitAlignPoint(){
        return this.hitAlignPoint;
    }
    
    public boolean isHitAlignUpperLeft(){
        int alignAxis=this.targetAlign.getAlignAxis();
        double delta=0.0;
        if(alignAxis==Align.XALIGN) 
            delta=this.hitAlignPoint.getY()-this.targetAlignPoint.getY();
        if(alignAxis==Align.YALIGN) 
            delta=this.hitAlignPoint.getX()-this.targetAlignPoint.getX();
        boolean forward=true;
        if(delta>0d) forward=false;
        return forward;
    }
	
	
    public double getAlignOrthogonalDistance(){
        int alignAxis=this.targetAlign.getAlignAxis();
        double dist=0;
        if(alignAxis==Align.XALIGN) 
            dist=Math.abs(this.targetAlignPoint.getY()-this.hitAlignPoint.getY());
        if(alignAxis==Align.YALIGN) 
            dist=Math.abs(this.targetAlignPoint.getX()-this.hitAlignPoint.getX());
        return dist;
    }
	
	public double getAlignedError() {
		double error = ErrorMax;
		int targetAlignType = this.targetAlign.getAlignType();
		int hitAlignType = this.hitAlign.getAlignType();
		Rectangle2D targetBox = this.targetAlign.getBoundingBox();
		Rectangle2D hitBox = this.hitAlign.getBoundingBox();
		double target[] = new double[3];
		double hit[] = new double[3];
		if ((targetAlignType < 3 || targetAlignType == Align.ENDPT) && hitAlignType < 3) {
			for (int i = 0; i < 3; i++) {
				target[i] = targetBox.getX() + 0.5 * targetBox.getWidth() * i;
				hit[i] = hitBox.getX() + 0.5 * hitBox.getWidth() * i;
			}
			if (this.targetAlign.getAlignType() != Align.ENDPT) {
				error = hit[hitAlignType] - target[targetAlignType];
			} else {
				Point2D[] endPTs = this.targetAlign.shapeContainer.getElement().getEndPTs();
				Point2D endPT = endPTs[this.targetAlign.getEndPTindex()];
				error = hit[hitAlignType] - endPT.getX();
			}

		} else if ((targetAlignType >= 3 || targetAlignType == Align.ENDPT) && hitAlignType >= 3) {
			for (int i = 0; i < 3; i++) {
				target[i] = targetBox.getY() + 0.5 * targetBox.getHeight() * i;
				hit[i] = hitBox.getY() + 0.5 * hitBox.getHeight() * i;
			}
			if (this.targetAlign.getAlignType() != Align.ENDPT) {
				error = hit[hitAlignType - 3] - target[targetAlignType - 3];
			} else {
				Point2D[] endPTs = this.targetAlign.shapeContainer.getElement().getEndPTs();
				Point2D endPT = endPTs[this.targetAlign.getEndPTindex()];
				error = hit[hitAlignType - 3] - endPT.getY(); //bug
			}
		}
		return error;
	}

	public double[] checkIntersection(){
		double[] interval=null;
		int targetAlignAxis = this.targetAlign.getAlignAxis();
		int targetAlignType = this.targetAlign.getAlignType();
		int hitAlignType = this.hitAlign.getAlignType();
		double targetValue=this.targetAlign.getValue();
		double hitValue=this.hitAlign.getValue();
		double errorMargin=AutoAlign.ErrorMargin;
		Rectangle2D targetBox=this.targetAlign.getBoundingBox();
		Rectangle2D hitBox=this.hitAlign.getBoundingBox();
		Rectangle2D targetChkBox=null;
		Rectangle2D hitChkBox=null;
		double delta=1.0;
		if (targetAlignAxis == Align.XALIGN) {
			targetChkBox = new Rectangle2D.Double(targetValue - errorMargin, targetBox.getY(),
					2.0*errorMargin, targetBox.getHeight());
			hitChkBox = new Rectangle2D.Double(hitValue, hitBox.getY(),
					0, hitBox.getHeight());
		} else {
			targetChkBox = new Rectangle2D.Double(targetBox.getX(), hitValue-errorMargin,
					targetBox.getWidth(), 2.0*errorMargin);
			hitChkBox = new Rectangle2D.Double(hitBox.getX(), hitValue,
					hitBox.getWidth(), 0);
		}
		Rectangle2D intersect = new Rectangle2D.Double(0, 0, 0, 0);
		Rectangle2D.intersect(targetChkBox, hitChkBox, intersect);
		
		if (intersect.getWidth()>0.0d||intersect.getHeight()>0.0d){
			interval=new double[2];
			if (targetAlignAxis == Align.XALIGN) {
				interval[0] = intersect.getY();
				interval[1] = intersect.getY() + intersect.getHeight();
			} else {
				interval[0] = intersect.getX();
				interval[1] = intersect.getX() + intersect.getWidth();
			}
		}
		if(debug>0){
			String str="";
			str+=" - AlignedCouples checkInterSection\n";
			String space = "  ";
			str+="  targetAlign: " + targetAlign.toString(2)
					+ "\n  hitAlign:    " + hitAlign.toString(2);
			str+="\n  targetChkBox: "+Util.RectC(targetChkBox)+"\n";
			str+="  hitChkBox: "+Util.RectC(hitChkBox)+"\n";
			if(interval==null){
				str+="  intersect=null";
			} else{
				str+="  intersect: "+Util.Rect(intersect)+", interval=("+interval[0]+", "+interval[1]+")";
			}
			System.out.println(str);
		}
		return interval;
	}
	
    public void update(){
		this.targetAlign.update();
		this.hitAlign.update();
		this.setAlignPoints();
	}
	
    public String toString(){
        String str="targetAlign: "+targetAlign.toString()+
                 "\nhitAlign:    "+hitAlign.toString();
		double[] intersect=this.checkIntersection();
		if(intersect==null){
			str+="\nintersect=none";
		}else{
			str+="\nintersect=("+intersect[0]+", "+intersect[1]+")";
		}
        return str;
    }
	public String toString(int indent) {
		String space = "";
		for (int i = 0; i < indent; i++) {
			space += " ";
		}
		String str = space+"targetAlign: " + targetAlign.toString(indent)
				+ "\n"+space+"hitAlign:    " + hitAlign.toString(indent);
		double[] intersect = this.checkIntersection();
		if (intersect == null) {
			str += "\n"+space+ "intersect=none";
		} else {
			str += "\n"+space+ "intersect=(" + intersect[0] + ", " + intersect[1] + ")";
		}
		return str;
	}
}