/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package shapeUtil;

import shape.*;
import java.awt.*;
import java.awt.geom.*;
import util.*;
import DrawTop.*;
import geomExtension.*;

public class Connection {
    public ShapeContainer target=null;
    public ShapeContainer connector=null;
    public double targetParameter;
    public double connectorParameter;
    public static int debug=0;
    
    public Connection(){}

    public Connection(ShapeContainer target, ShapeContainer connector, 
            double targetParameter, double connectorParameter){
        this.target=target;
        this.connector=connector;
        this.targetParameter=targetParameter;
        this.connectorParameter=connectorParameter;
    }

    public ShapeContainer getTarget(){
        return this.target;
    }
    
    public ShapeContainer getConnector(){
        return this.connector;
    }
    
    public void setTargetParameter(double targetParameter){
        this.targetParameter=targetParameter;
    }
    
    public double getTargetParameter(){
        return this.targetParameter;
    }
    
    public void setConnectorParameter(double connectorParameter){
        this.connectorParameter=connectorParameter;
    }
    
    public double getConnectorParameter(){
        return this.connectorParameter;
    }
    
    public Point2D getTargetPT(){
        Curve2D curve=this.target.getElement().getCurve2D();
        return curve.getP(this.targetParameter);
    }

    public Point2D getConnectorPT(){
        Curve2D curve=this.connector.getElement().getCurve2D();
        return curve.getP(this.connectorParameter);
    }
    
    public Vector2D getTargetTangent(){
        Curve2D curve=this.target.getElement().getCurve2D();
        return curve.getTangent(this.targetParameter);
    }
    
    public Vector2D getConnectorTangent(){
        Curve2D curve=this.connector.getElement().getCurve2D();
        return curve.getTangent(this.connectorParameter);
    }
    
    public boolean equalsInNormalData(Connection connection){
        double eps=1.0e-10;
        if(connection.getTarget().getSerialNumber()!=this.getTarget().getSerialNumber())  return false;
        if(connection.getConnector().getSerialNumber()!=this.getConnector().getSerialNumber()) return false;
        double delta=connection.getTargetParameter()-this.getTargetParameter();
        if(Math.abs(delta)>eps) return false;
        delta=connection.getConnectorParameter()-this.getConnectorParameter();
        if(Math.abs(delta)>eps) return false;
        return true;
    }
    
    public boolean equalsInReversedData(Connection connection){
        double eps=1.0e-10;
        if(connection.getTarget().getSerialNumber()!=this.getConnector().getSerialNumber())  return false;
        if(connection.getConnector().getSerialNumber()!=this.getTarget().getSerialNumber()) return false;
        double delta=connection.getTargetParameter()-this.getConnectorParameter();
        if(Math.abs(delta)>eps) return false;
        delta=connection.getConnectorParameter()-this.getTargetParameter();
        if(Math.abs(delta)>eps) return false;
        return true;
    }

    public double getErrorDistance(){
        Point2D p0=this.connector.getElement().getCurve2D().getP(this.connectorParameter);
        Point2D p1=this.target.getElement().getCurve2D().getP(this.targetParameter);
        double dist=Vector2D.dist(p0, p1);
        if(dist<1.0e-10) dist=0.0;
        return dist;
    }
    
    protected boolean closeToMouseHitShape(MouseHitShape mouseHitShape){
        int endPTindex=-1;
        if(mouseHitShape!=null) {
            int index=mouseHitShape.getEndIndexCloseToMouse();
            if(index>=0) endPTindex=index;
        }
        boolean exceptional=false;
        if(mouseHitShape==null||endPTindex<0) return false;
        ShapeContainer mouseHitContainer=mouseHitShape.getShapeContainer();
        Point2D mousePT=mouseHitShape.getMousePosition();
        ShapeContainer target=this.getTarget();
        if(target.compare(mouseHitContainer)){
            Point2D targetP=this.getTargetPT();
            if(Vector2D.dist(mousePT, targetP)<DrawParameters.Mark_NormalSize) exceptional=true;
        }
        ShapeContainer connector=this.getConnector();
        if(connector.compare(mouseHitContainer)){
            Point2D connectorP=this.getConnectorPT();
            if(Vector2D.dist(mousePT, connectorP)<DrawParameters.Mark_NormalSize) exceptional=true;
        }
        if(debug>0) System.out.println("isEndPTConnection  exceptional="+exceptional+
                ",  mouseHitContainer="+mouseHitContainer.getShapeId()+", endPTindex="+endPTindex+
                "\n       connection="+this.toString());
        return exceptional;
    }

    protected void resizeConnector(Point2D oldPoint, Point2D newPoint){
        double dist=Vector2D.dist(oldPoint, newPoint);
        if( dist<1.0e-12) return;
        ShapeElement shapeElement=this.connector.getElement();
        int index=0;
        if(this.getConnectorParameter()>0.0) index=1;
        shapeElement.moveEndPoint(0, index, oldPoint, newPoint);
        if(debug>0) System.out.println("resizeConnector, connection="+this.toString());
    }
    
    protected void resizeTarget(Point2D oldPoint, Point2D newPoint){
        ShapeElement shapeElement=this.target.getElement();
        int index=0;
        if(this.getTargetParameter()>0.0) index=1;
        shapeElement.moveEndPoint(0, index, oldPoint, newPoint);
    }
    
    public String toShortString(){
        String str="";
        str+=" target="+target.getShapeId()+", connector="+connector.getShapeId()+
                ", error distance="+this.getErrorDistance();
        return str;
    }
    
    public String toString(){
        String str="";
        str+=" target="+target.getShapeId()+", connector="+connector.getShapeId()+ 
                ", targetP="+Util.Num(this.targetParameter)+
                ", connectorP="+Util.Num(this.connectorParameter)+
                ", targetPT="+Util.Pt(this.getTargetPT())+
                ", connectorPT="+Util.Pt(this.getConnectorPT())+
                ", error distance="+this.getErrorDistance();
        return str;
    }
    
    public Object clone(){
        ShapeContainer targetC=(ShapeContainer)this.target.clone();
        ShapeContainer connectorC=(ShapeContainer)this.connector.clone();
        double targetPara=this.getTargetParameter();
        double connectorPara=this.getConnectorParameter();
        Connection connection=new Connection(targetC, connectorC, 
                targetPara, connectorPara);
        return connection;
    }
    
    public static boolean isConnectorType(ShapeContainer connector){
        if(connector.getElement()==null) return false;
        int connectorType=connector.getElement().getTypeE();
        if(connectorType!=Command.LINE&&connectorType!=Command.ARROW
                &&connectorType!=Command.DOUBLE_ARROW
                &&connectorType!=Command.POLYLINE) return false;
        if(connector.getElement().isClosed()) return false;
        return true;
    }
    
    public static boolean isTargetType(ShapeContainer target){
        if(target.getContainerType()==ShapeContainer.GROUP) return false;
        if(target.getElement()==null) return false;
        return true;
    }

}