package shapeUtil;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Vector;
import shape.ShapeContainer;
import util.*;


class Align{
    int alignAxis=-1;
    int alignType=-1;
    double value;
    ShapeContainer shapeContainer=null;
    int endPTindex=-1;
    Rectangle2D boundingBox=null;
    Point2D[] alignedPoints=null;
	
	static final int XALIGN=10;
    static final int YALIGN=11;
    
    static final int LEFT=0;
    static final int CENTER=1;
    static final int RIGHT=2;
    static final int TOP=3;
    static final int MIDDLE=4;
    static final int BOTTOM=5;
    static final int ENDPT=6;

	static final String[] alignString = {"LEFT", "CENTER", "RIGHT", "TOP", "MIDDLE", "BOTTOM", "ENDPT",
									 "", "", "", "X-ALIGN", "Y-ALIGN"};
	
    Align(int alignAxis, int alignType, double value, ShapeContainer shapeContainer){
        this.alignAxis=alignAxis;
        this.alignType=alignType;
        this.value=value;
        this.shapeContainer=shapeContainer;
        this.endPTindex=-1;
        this.setBoundingBox();
        this.setAlignedPoints();
    }

    Align(int alignAxis, int alignType, double value,  ShapeContainer shapeContainer,
            int endPTindex){
        this.alignAxis=alignAxis;
        this.alignType=alignType;
        this.value=value;
        this.shapeContainer=shapeContainer;
        this.endPTindex=endPTindex;
        this.setBoundingBox();
		this.setAlignedPoints();
		if (endPTindex >= 0) {
			Point2D[] PTs = this.shapeContainer.getElement().getEndPTs();
			this.boundingBox = new Rectangle2D.Double(PTs[endPTindex].getX(), PTs[endPTindex].getY(), 0, 0);
			this.alignedPoints = new Point2D[1];
			this.alignedPoints[0] = new Point2D.Double(PTs[endPTindex].getX(), PTs[endPTindex].getY());
		} 
		//else{
		//	System.err.println("**** Error Align constructor endPTindex<0"
		//			+ ", alignAxis=" + alignString[alignAxis] + ", alignType=" + alignString[alignType]);
		//}
    }
    
    private void setBoundingBox(){
        Rectangle2D box=null;
        int endPTindex=this.getEndPTindex();
        if(this.getAlignType()==Align.ENDPT){
            if(endPTindex>=0){
                Point2D[] PTs=this.getShapeContainer().getElement().getEndPTs();
                box=new Rectangle2D.Double(PTs[endPTindex].getX(), 
                        PTs[endPTindex].getY(), 0, 0);
            }
        } else {
            box=this.getShapeContainer().getBoundingBox();
        }
        this.boundingBox=box;
    }

    private void setAlignedPoints(){
        Rectangle2D box=this.getBoundingBox();
        double x=box.getX();
        double y=box.getY();
        double w=box.getWidth();
        double h=box.getHeight();
        double X=-1e+4;
        double Y=-1e+4;
        
        //double eps=1e-1;
        Point2D[] points=new Point2D[1];
        int alignAxis=this.getAlignAxis();
        int alignType=this.getAlignType();
        if(alignType==Align.LEFT){
            X=x;
            points[0]=new Point2D.Double(x, y+0.5*h);
        }
        if(alignType==Align.CENTER){
            X=x+0.5*w;
            points[0]=new Point2D.Double(x+0.5*w, y+0.5*h);
        }
        if(alignType==Align.RIGHT){
            X=x+w;
            points[0]=new Point2D.Double(x+w, y+0.5*h);
        }
        if(alignType==Align.TOP){
            Y=y;
            points[0]=new Point2D.Double(x+0.5*w, y);
        }
        if(alignType==Align.MIDDLE){
            Y=y+0.5*h;
            points[0]=new Point2D.Double(x+0.5*w, y+0.5*h);
        }
        if(alignType==Align.BOTTOM){
            Y=y+h;
            points[0]=new Point2D.Double(x+0.5*w, y+h);
        }
        if(alignType==Align.ENDPT)   points[0]=new Point2D.Double(x,y);
        
		if (alignType != Align.ENDPT){
			double eps=1;
			Vector vector = new Vector();
			ShapeContainer[] containers = this.getShapeContainer().getGroupedSingleShapeContainers();
			for (int j = 0; j < containers.length; j++) {
				Point2D[] PTs = containers[j].getElement().getCurve2D().getSamplingPTs(0.5 * AutoAlign.ErrorMargin);
				for (int i = 0; i < PTs.length; i++) {
					x = PTs[i].getX();
					y = PTs[i].getY();
					if (alignAxis == Align.XALIGN) {
						if (Math.abs(X - x) < eps) {
							vector.add(PTs[i]);
						}
					}
					if (alignAxis == Align.YALIGN) {
						if (Math.abs(Y - y) < eps) {
							vector.add(PTs[i]);
						}
					}
				}
			}
			int size = vector.size();
			if (size > 0) {
				points = new Point2D[size];
				for (int i = 0; i < size; i++) {
					points[i] = (Point2D) vector.get(i);
				}
			}
		} //end of if(alignType != Align.ENDPT)
		
        this.alignedPoints=points;
    }
    
    int getAlignAxis(){
        return this.alignAxis;
    }
    
    int getAlignType(){
        return this.alignType;
    }
    
    double getValue(){
        return this.value;
    }
    
    ShapeContainer getShapeContainer(){
        return this.shapeContainer;
    }
    
    int getEndPTindex(){
        return this.endPTindex;
    }
    
    Rectangle2D getBoundingBox(){
        return this.boundingBox;
    }
    
    public Point2D[] getAlignedPoints(){
        return this.alignedPoints;
    }
	
    public void update(){
		this.setBoundingBox();
		this.setAlignedPoints();
		if (endPTindex >= 0) {
			Point2D[] PTs = this.shapeContainer.getElement().getEndPTs();
			this.boundingBox = new Rectangle2D.Double(PTs[endPTindex].getX(), PTs[endPTindex].getY(), 0, 0);
			this.alignedPoints = new Point2D[1];
			this.alignedPoints[0] = new Point2D.Double(PTs[endPTindex].getX(), PTs[endPTindex].getY());
		} 
	}
	
    public String toString(){
		String axisStr="undef";
		String typeStr="undef";
		String boxStr="null";
		if(this.alignAxis>=0) axisStr=alignString[this.alignAxis];
		if(this.alignType>=0) typeStr=alignString[this.alignType];
		if(this.boundingBox!=null) boxStr=Util.Rect(this.boundingBox);
		
        String str="axis="+axisStr+", type="+typeStr
				+ ", value="+this.value+","
				+"\nboundingBox: "+boxStr+
                ", ShapeContainer="+this.shapeContainer.getShapeId();
        return str;
    }

	public String toString(int indent){
		String space="";
		for(int i=0;i<indent;i++){
			space+=" ";
		}
		String axisStr="undef";
		String typeStr="undef";
		String boxStr="null";
		if(this.alignAxis>=0) axisStr=alignString[this.alignAxis];
		if(this.alignType>=0) typeStr=alignString[this.alignType];
		if(this.boundingBox!=null) boxStr=Util.Rect(this.boundingBox);
		
        String str=space+"axis="+axisStr+", type="+typeStr+
                ", value="+this.value+","
				+"\n"+space+"boundingBox: "+boxStr+
                ", ShapeContainer="+this.shapeContainer.getShapeId();
        return str;
    }
		
}// end of Align
