import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.util.ArrayList;
import java.util.Vector;


public class Edge_transition 

{
    public static final int    WIDTH = 7;

    private String	    			label;
    private Node_Rectangular	    startNode, endNode;
    
    
    
    private boolean     selected;
    private String		equation;	
    private	int 		xpos_equation;
	private int 		ypos_equation;
    private boolean		manual_startPt;
    private boolean 	config_text_condition;
    
    int text_x = 0;
    int text_y = 0;
    int width_string = 0;
    int height_string = 0;
    
    int shift_text_x = 0;
    int shift_text_y = 0;
    
    boolean shift_text_auto = true;
    boolean shift_text_manual = false;
    
    private static final int MIN_SEGMENT = 10;
    
    String mode_edge = "HVH";
    
    //STRAIGHT, HV, VH, HVH, VHV;

    public Edge_transition(Node_Rectangular n1, Node_Rectangular n2) 
    { 
    	this("", n1, n2); 
    }

    public Edge_transition(String aLabel, Node_Rectangular n1, Node_Rectangular n2) 
    {
        label = aLabel;
        startNode = n1;
        endNode = n2;
        selected = false;
        equation = "abc..";
        xpos_equation = 0;
    	ypos_equation = 0;

    	shift_text_x = 99;
        shift_text_y = -45;
        
    	
    	manual_startPt = false;
        
    }
    
  /*
	  public void connect(Node_Rectangular s, Node_Rectangular e)
	  {  
		  startNode = s;
		  endNode   = e;
	  }
*/
    
    public Node_Rectangular getStart()
    {
       return startNode;
    }

    public Node_Rectangular getEnd()
    {
       return endNode;
    }
    
    public void draw(Graphics2D g2)
	{
    	
		//g2.setColor(Color.GREEN);
		//g2.drawLine(startNode.getX1(), startNode.getY1(), endNode.getX1(), endNode.getY1());
		
		
		ArrayList points = getPoints();
	      
	    // Stroke oldStroke = g2.getStroke();
	    //g2.setStroke(lineStyle.getStroke());

		 GeneralPath path = new GeneralPath();
	     Point2D p = (Point2D) points.get(points.size() - 1);
	     path.moveTo((float) p.getX(), (float) p.getY());
	     
	     for (int i = points.size() - 2; i >= 0; i--)
	     {
	          p = (Point2D) points.get(i);
	          path.lineTo((float) p.getX(), (float) p.getY());
	     }
		
	     g2.draw(path);
    	
	}
    
    public ArrayList<Point2D> getPoints()
    {
    	Rectangle2D start = new Rectangle2D.Double(startNode.getX1(), startNode.getY1(), startNode.getWidth(), startNode.getHeight() );
    	Rectangle2D end = new Rectangle2D.Double(endNode.getX1(), endNode.getY1(), endNode.getWidth(), endNode.getHeight() );
    	
        return getPath( start,  end);
    }
    
    
    public ArrayList<Point2D> getPath(Rectangle2D start, Rectangle2D end)
    {
       ArrayList<Point2D> r = xxx_getPath(mode_edge, start, end);
       if (r != null) return r;

       if (mode_edge == "HVH") r = xxx_getPath("VHV", start, end);
       else if (mode_edge == "VHV") r = xxx_getPath("HVH", start, end);
       else if (mode_edge == "HV") r = xxx_getPath("VH", start, end);
       else if (mode_edge == "VH") r = xxx_getPath("HV", start, end);
       if (r != null) return r;

       //return getPath("STRAIGHT", start, end);
       return null;
    }

   
    private static Point2D[] connectionPoints(Rectangle2D r)
    {
       Point2D[] a = new Point2D[4];
       a[0] = new Point2D.Double(r.getX(), r.getCenterY());
       a[1] = new Point2D.Double(r.getMaxX(), r.getCenterY());
       a[2] = new Point2D.Double(r.getCenterX(), r.getY());
       a[3] = new Point2D.Double(r.getCenterX(), r.getMaxY());
       return a;
    }

    /**
       Gets the points at which a line joining two rectangles
       is bent according to a bent style.
       @param start the starting rectangle
       @param end the ending rectangle
       @return an array list of points at which to bend the
       segmented line joining the two rectangles
    */
    private static ArrayList<Point2D> xxx_getPath(String mode_edge,  Rectangle2D s, Rectangle2D e)
    {
       ArrayList<Point2D> r = new ArrayList<Point2D>();
       if (mode_edge == "STRAIGHT")
       {
          Point2D[] a = connectionPoints(s);
          Point2D[] b = connectionPoints(e);
          Point2D p = a[0];
          Point2D q = b[0];
          double distance = p.distance(q);
          //for (int i = 0; i < a.length; i++)
          for (Point2D point1 : a)
             //for (int j = 0; j < b.length; j++)
             for (Point2D point2 : b)
             {
                double d = point1.distance(point2);
                if (d < distance)
                {
                   p = point1; q = point2;
                   distance = d;
                }
             }
          r.add(p);
          r.add(q);
       }
       else if (mode_edge == "HV")
       {
          double x1;
          double x2 = e.getCenterX();
          double y1 = s.getCenterY();
          double y2;
          if (x2 + MIN_SEGMENT <= s.getX())
             x1 = s.getX();
          else if (x2 - MIN_SEGMENT >= s.getMaxX())
             x1 = s.getMaxX();
          else return null;
          if (y1 + MIN_SEGMENT <= e.getY())
             y2 = e.getY();
          else if (y1 - MIN_SEGMENT >= e.getMaxY())
             y2 = e.getMaxY();
          else return null;
          r.add(new Point2D.Double(x1, y1));
          r.add(new Point2D.Double(x2, y1));
          r.add(new Point2D.Double(x2, y2));
       }
       else if (mode_edge == "VH")
       {
          double x1 = s.getCenterX();
          double x2;
          double y1;
          double y2 = e.getCenterY();
          if (x1 + MIN_SEGMENT <= e.getX())
             x2 = e.getX();
          else if (x1 - MIN_SEGMENT >= e.getMaxX())
             x2 = e.getMaxX();
          else return null;
          if (y2 + MIN_SEGMENT <= s.getY())
             y1 = s.getY();
          else if (y2 - MIN_SEGMENT >= s.getMaxY())
             y1 = s.getMaxY();
          else return null;
          r.add(new Point2D.Double(x1, y1));
          r.add(new Point2D.Double(x1, y2));
          r.add(new Point2D.Double(x2, y2));
       }
       else if (mode_edge == "HVH")
       {
          double x1;
          double x2;
          double y1 = s.getCenterY();
          double y2 = e.getCenterY();
          if (s.getMaxX() + 2 * MIN_SEGMENT <= e.getX())
          {
             x1 = s.getMaxX();
             x2 = e.getX();
          }
          else if (e.getMaxX() + 2 * MIN_SEGMENT <= s.getX())
          {
             x1 = s.getX();
             x2 = e.getMaxX();
          }
          else return null;
          if (Math.abs(y1 - y2) <= MIN_SEGMENT)
          {
             r.add(new Point2D.Double(x1, (y1 + y2) / 2));
             r.add(new Point2D.Double(x2, (y1 + y2) / 2));
          }
          else
          {
             r.add(new Point2D.Double(x1, y1));
             r.add(new Point2D.Double((x1 + x2) / 2, y1));
             r.add(new Point2D.Double((x1 + x2) / 2, y2));
             r.add(new Point2D.Double(x2, y2));
          }
       }
       else if (mode_edge == "VHV")
       {
          double x1 = s.getCenterX();
          double x2 = e.getCenterX();
          double y1;
          double y2;
          if (s.getMaxY() + 2 * MIN_SEGMENT <= e.getY())
          {
             y1 = s.getMaxY();
             y2 = e.getY();
          }
          else if (e.getMaxY() + 2 * MIN_SEGMENT <= s.getY())
          {
             y1 = s.getY();
             y2 = e.getMaxY();

          }
          else return null;
          if (Math.abs(x1 - x2) <= MIN_SEGMENT)
          {
             r.add(new Point2D.Double((x1 + x2) / 2, y1));
             r.add(new Point2D.Double((x1 + x2) / 2, y2));
          }
          else
          {
             r.add(new Point2D.Double(x1, y1));
             r.add(new Point2D.Double(x1, (y1 + y2) / 2));
             r.add(new Point2D.Double(x2, (y1 + y2) / 2));
             r.add(new Point2D.Double(x2, y2));
          }
       }
       else return null;
       return r;
    }
    
    
    private GeneralPath getSegmentPath()
    {
       ArrayList points = getPoints();
       
       GeneralPath path = new GeneralPath();
       Point2D p = (Point2D) points.get(points.size() - 1);
       path.moveTo((float) p.getX(), (float) p.getY());
       for (int i = points.size() - 2; i >= 0; i--)
       {
          p = (Point2D) points.get(i);
          path.lineTo((float) p.getX(), (float) p.getY());
       }
       return path;
    }
}
