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 *********
	System.out.println("Entering Cohen-Sutherland");
        LineSegment ls = new LineSegment();

	int bc = outcode(x1,y1, vp.top, vp.bottom, vp.left, vp.right);
	int ec = outcode(x2,y2, vp.top, vp.bottom, vp.left, vp.right);

        int bc1=bc/1000;
	if (bc>=1000) { bc=bc-1000;} int bc2=bc/100;
	if (bc>=100) { bc=bc-100;} int bc3=bc/10;
	if (bc>=10) { bc=bc-10;} int bc4=bc/1;

        int ec1=ec/1000;
        if (ec>=1000) { ec=ec-1000;} int ec2=ec/100;
        if (ec>=100) { ec=ec-100;} int ec3=ec/10;
        if (ec>=10) { ec=ec-10;} int ec4=ec/1; 

	System.out.println(bc1+bc2+bc3+bc4 + "  " + ec1+ec2+ec3+ec4);

	if (bc1+bc2+bc3+bc4+ec1+ec2+ec3+ec4==0) {
           ls.setClipType("internal");
           ls.x1 = x1;
	   ls.y1 = y1;
	   ls.x2 = x2;
	   ls.y2 = y2;
	} else 
	if (bc1+ec1==2 || bc2+ec2==2 || bc3+ec3==2 || bc4+ec4==2) {
           ls.setClipType("external");
	   ls.x1 = 0;
	   ls.y1 = 0;
	   ls.x2 = 0;
	   ls.y2 = 0;
	} else

        while (bc1+bc2+bc3+bc4+ec1+ec2+ec3+ec4 != 0 && !(bc1+ec1==2 || bc2+ec2==2 || bc3+ec3==2 || bc4+ec4==2) ) { 
           ls.setClipType("clipped");

           if (bc1==1) {
	      System.out.println("Clipping top");
	      x1 = x1 + (vp.top-y1)/(y2-y1)*(x2-x1);
              y1 = vp.top;
           } else
	   if (bc2==1) {
	      System.out.println("Clipping bottom");
	      x1 = x1 + (vp.bottom-y1)/(y2-y1)*(x2-x1);
	      y1 = vp.bottom;
	   } else
	   if (bc3==1) {
	      System.out.println("Clipping right");
	      y1 = y1 + (vp.right-x1)/(x2-x1)*(y2-y1);
	      x1 = vp.right;
	   } else
           if (bc4==1) {
	      System.out.println("Clipping left");
	      y1 = y1 + (vp.left-x1)/(x2-x1)*(y2-y1);
	      x1 = vp.left;
	   } else
           if (ec1==1) {
	      System.out.println("Clipping top");
	      x2 = x1 + (vp.top-y1)/(y2-y1)*(x2-x1);
	      y2 = vp.top;
	   } else
	   if (ec2==1) {
	      System.out.println("Clipping bottom");
	      x2 = x1 + (vp.bottom-y1)/(y2-y1)*(x2-x1);
	      y2 = vp.bottom;
	   } else
	   if (ec3==1) {
       	      System.out.println("Clipping right");
	      y2 = y1 + (vp.right-x1)/(x2-x1)*(y2-y1);
	      x2 = vp.right;
	   } else
	   if (ec4==1) {
	      System.out.println("Clipping left");
	      y2 = y1 + (vp.left-x1)/(x2-x1)*(y2-y1);
	      x2 = vp.left;
	   }

           bc = outcode(x1,y1, vp.top, vp.bottom, vp.left, vp.right);
	   ec = outcode(x2,y2, vp.top, vp.bottom, vp.left, vp.right);

           bc1=bc/1000;
	   if (bc>=1000) { bc=bc-1000;} bc2=bc/100;
	   if (bc>=100) { bc=bc-100;} bc3=bc/10;
	   if (bc>=10) { bc=bc-10;} bc4=bc/1;

	   ec1=ec/1000;
	   if (ec>=1000) { ec=ec-1000;} ec2=ec/100;
	   if (ec>=100) { ec=ec-100;} ec3=ec/10;
	   if (ec>=10) { ec=ec-10;} ec4=ec/1;

        } //while

        if (bc1+ec1==2 || bc2+ec2==2 || bc3+ec3==2 || bc4+ec4==2) {
	   ls.setClipType("external");
	   ls.x1 = 0;
	   ls.y1 = 0;
	   ls.x2 = 0;
	   ls.y2 = 0;
	} else {
	   ls.x1 = x1;
	   ls.y1 = y1;
	   ls.x2 = x2;
	   ls.y2 = y2;
        }
        return ls;

    }

    /*
      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 (y>top) { result = result+1000; }
        if (y<bottom) { result = result+100; }
        if (x>right) { result = result+10; }
        if (x<left) { result = result+1; }
	return result;
    }	
}
