import display.*;

public class CohenSutherland {

  public static final int LEFT = 1;
  public static final int RIGHT = 2;
  public static final int TOP = 4;
  public static final int BOTTOM = 8;
    
  /*
    Inputs: the original line from (x1,y1) to (x2,y2), and a
    viewport The viewport object has four public instance variables,
    which can be accessed by: 
    var1 = viewport.top; 
    var2 = viewport.bottom; 
    var3 = viewport.left; 
    var4 = viewport.right;

    Output: a LineSegment object 
    You can create a LineSegment object by making the call
    LineSegment ls = new LineSegment()

    Having created it, you must set five values: 
    x1, y1, x2, y2    the coordinates of each of the
    endpoints of the clipped line You set
    these values by including the line
    ls.setEndPoints(x1, y1, x2, y2); 
    or alternatively, by setting each of
    the endpoints individually: 
    ls.x1 = x1;
    ls.y1 = y1; 
    etc.

    clipType          The clip type can be set to three
    values:

    "internal" if the input line segment
    falls entirely within the clip region,
    otherwise:

    "clipped" if it was determined that
    some part of the input line segment does
    fall within the boundaries defined by the
    clip region, otherwise:

    "external" if NO part of the input
    line segment falls within the clip region
    (i.e. the entire line was clipped.)
                              
    You can set these values by including
    the java statements:
    ls.setClipType("internal");
    OR
    ls.setClipType("clipped");
    OR
    ls.setClipType("external");
    
    NOTE: If you want to have any auxiliary methods (helpers), you
    must make sure to declare them "static" as well.
  */

  public static LineSegment ClipSegment(double x1, double y1, 
					double x2, double y2, 
					Viewport vp) {

    // ******* YOUR CODE HERE *********

    //for debugging:
    System.out.println("Entering Cohen-Sutherland");

    double left = vp.left;
    double right = vp.right;
    double top = vp.top;
    double bottom = vp.bottom;

    boolean clipped = false;
    
    LineSegment ls = new LineSegment();

    int outcode1 = outcode(x1, y1, top, bottom, left, right);
    int outcode2 = outcode(x2, y2, top, bottom, left, right);

    System.out.println(outcode1);
    System.out.println(outcode2);

    while(true){
      
      if((outcode1 & outcode2) > 0)
      {
	ls.x1 = 0.0;
	ls.y1 = 0.0;
	ls.x2 = 0.0;
	ls.y2 = 0.0;
	ls.setClipType("external");
	return ls;
      }
      else if((outcode1 + outcode2) == 0)
      {
	ls.x1 = x1;
	ls.y1 = y1;
	ls.x2 = x2;
	ls.y2 = y2;
	if(clipped)
	{
	  ls.setClipType("clipped");
	}
	else
	{
	  ls.setClipType("internal");
	}
	return ls;
      }
      else if(!((outcode1 & outcode2) > 0) && !((outcode1 + outcode2) == 0))
      {
	//	int neededclips = (outcode1 | outcode2);
	if((outcode1 & LEFT) == LEFT)
	{
	  y1 = intersect(y1, y2, x1, x2, left);
	  x1 = left;
	}else if((outcode2 & LEFT) == LEFT)
	{
	  y2 = intersect(y2, y1, x2, x1, left);
	  x2 = left;
	}else if((outcode1 & RIGHT) == RIGHT)
	{
	  y1 = intersect(y1, y2, x1, x2, right);
	  x1 = right;
	}else if((outcode2 & RIGHT) == RIGHT)
	{
	  y2 = intersect(y2, y1, x2, x1, right);
	  x2 = right;
	}else if((outcode1 & TOP) == TOP)
	{
	  x1 = intersect(x1, x2, y1, y2, top);
	  y1 = top;
	}else if((outcode2 & TOP) == TOP)
	{
	  x2 = intersect(x2, x1, y2, y1, top);
	  y2 = top;
	}else if((outcode1 & BOTTOM) == BOTTOM)
	{
	  x1 = intersect(x1, x2, y1, y2, bottom);
	  y1 = bottom;
	}else if((outcode2 & BOTTOM) == BOTTOM)
	{
	  x2 = intersect(x2, x1, y2, y1, bottom);
	  y2 = bottom;
	}
	outcode1 = outcode(x1, y1, top, bottom, left, right);
	outcode2 = outcode(x2, y2, top, bottom, left, right);
	clipped = true;
      }
    }
  }


  /*
    This method, given a point (x,y) and some clip region
    boundaries, should produce the binary clip codes for the
    Cohen-Sutherland algorithm.  
  */
  public static int outcode(double x, double y,
			    double top, double bottom, 
			    double left, double right) {

    int result = 0;
    if(x < left) result +=  LEFT;
    if(x > right) result += RIGHT;
    if(y > top) result += TOP;
    if(y < bottom) result += BOTTOM;
    return result;
  }

  public static double intersect(double var_clip, double var_0,
				 double other, double other_0, double clip){
    
    double t = (clip - other_0)/(other - other_0);
    return var_0 + t*(var_clip-var_0);
   
  }
    
}





