import java.awt.Point;
import java.awt.geom.CubicCurve2D;
import java.util.Vector;

public class Loopback 
{
	   private Vector<Point> stateBorderPts;
	   private Point startPt, endPt, startCtrlPt,endCtrlPt;
	   private int startStateIndex,endStateIndex;
	   private CubicCurve2D.Double loop;
	   private  double alpha;
	   
	   int x = 0;
	   int y = 0;
	   int x0  = 0;
	   int y0  = 0;
	   int x1  = 0;
	   int y1 =  0;
	   
	   int[] xP =  {0,0,0}; 
       int[] yP = {0,0,0}; 
       
       public Loopback()
	   {
	   }
    	   
	   public Loopback(int x, int y, int x0, int y0, int x1, int y1)
	   {
		   
		   this.x = x;
		   this.y = y;
		   this.x0 = x0;
		   this.y0 = y0;
		   this.x1 = x1;
		   this.y1 = y1;
		   
		   setEndPts(x,y);
	       loop = new CubicCurve2D.Double(startPt.getX(),startPt.getY(),startCtrlPt.getX(),startCtrlPt.getY(),endCtrlPt.getX(),endCtrlPt.getY(),endPt.getX(),endPt.getY());
	 
	       alpha = getAngle(endCtrlPt,endPt);
	       
	       double adj = Math.PI/6;

	       int[] temp_x = {(int)endPt.getX(),(int)endPt.getX() + (int)(13*Math.cos(alpha + adj)),(int)endPt.getX() + (int)(13*Math.cos(alpha - adj))};
	       int[] temp_y = {(int)endPt.getY(),(int)endPt.getY() - (int)(13*Math.sin(alpha + adj)),(int)endPt.getY() - (int)(13*Math.sin(alpha - adj))};
      
		   this.xP = temp_x; 
		   this.yP = temp_y; 
		   
	   }
	   
	   public CubicCurve2D.Double get_loop()
	   {
		   return loop;
	   }
	   
	   public int[] get_array_xP()
	   {
		   return xP;
	   }
	   
	   public int[] get_array_yP()
	   {
		   return yP;
	   }
	   
	   private void setEndPts(int x, int y)
	   {
	        //find start point on oval closest to click point
	        stateBorderPts = getBorderPts();
	        Point createPt = new Point(x,y);
	        double temp;
	        double max = 1000000;
	        for(int i = 0; i < 36; i++)
	        {
	            temp = createPt.distanceSq(stateBorderPts.get(i));
	            if (temp < max)
	            {
	                startStateIndex = i;
	                max = temp;
	            }
	        }

	        // store two points on oval
	        startPt = stateBorderPts.get(startStateIndex);
	        endStateIndex = startStateIndex + 5;
	        if(endStateIndex > 35)
	            endStateIndex = endStateIndex - 36;
	        endPt = stateBorderPts.get(endStateIndex);

	        //angle control points are from points on oval
	        double angleStart = startStateIndex*2*Math.PI/36;
	        double angleEnd = endStateIndex*2*Math.PI/36;


	        //find distance from points on oval to control point
	        int dist = (int) Math.sqrt(get_size());

	        //scaling
	        dist = (int) (dist*.65);

	        //set up control points
	        startCtrlPt = new Point();
	        endCtrlPt = new Point();
	        startCtrlPt.setLocation((int) (dist*Math.cos(angleStart)) + startPt.getX(), dist*Math.sin(angleStart) + startPt.getY());
	        endCtrlPt.setLocation((int) (dist*Math.cos(angleEnd)) + endPt.getX(), dist*Math.sin(angleEnd) + endPt.getY());


	    }
	   
	   public Vector<Point> getBorderPts() 
	    {
	        Vector<Point> borderPts = new Vector<Point>(36);
	        
	        int w = x1 - x0;
	        int h = y1 - y0;
	        
	        for (int i = 0; i < 36; i++)
	        {
	            int x = (int) ((x0 + w / 2) + (w / 2)  * Math.cos((double) (2 * Math.PI / 36) * i));
	            int y = (int) ((y0 + h / 2) + (h / 2)  * Math.sin((double) (2 * Math.PI / 36) * i));
	            Point coord = new Point(x, y);
	            borderPts.add(i, coord);
	        }
	        
	        return borderPts;
	    }  
	
	   public int get_size() 
	   {
	        int a = (x1 - x0) * (y1 - y0);
	        return a;
	   }
	   
	   
	   public double getAngle(Point outer, Point inner)
	   {
	       int dx = (int) outer.getX() - (int) inner.getX();
	       int dy = -((int) outer.getY() - (int) inner.getY());
	       double alpha = 0;

	       if(dx == 0)
	       {
	           if(dy <= 0)
	               alpha = 3*Math.PI/2;
	           else
	               alpha = Math.PI/2;
	       }
	       //1st q
	       else if (dx > 0 && dy > 0)
	           alpha = Math.atan((double) dy/dx);
	       //4th q
	       else if (dx > 0 && dy <= 0)
	       {
	           if(dy == 0)
	               alpha = 0;
	           else
	               alpha = 2*(Math.PI) + Math.atan((double) dy/(dx));
	       }
	       //2nd, 3rd q
	       else if (dx < 0)
	           alpha = (Math.PI)+ Math.atan((double) dy/dx);
	       return alpha;
	   }
	   
}
