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");

	int code1, code2, tmpc;
	boolean done = false;
	boolean draw = false;
	double m = 0;
	double tmp;
	LineSegment ls = new LineSegment();
	ls.x1 = 0.0;
	ls.y1 = 0.0;
	ls.x2 = 0.0;
	ls.y2 = 0.0;
	ls.setClipType("internal");

	while (!done) {
		code1 = outcode(x1,y1,vp.top,vp.bottom,vp.left,vp.right);
		code2 = outcode(x2,y2,vp.top,vp.bottom,vp.left,vp.right);
		if((code1|code2) == 0) {
			//accept
			done = true;
			draw = true;
		}
		else
			if ((code1 & code2) != 0) {
				//reject
				ls.setClipType("external");
				done = true;
			}
			else {
				ls.setClipType("clipped");
				//make sure x1,y1 is the point outside the window
				if (code1 == 0) {
					tmp = x1;
					x1 = x2;
					x2 = tmp;
					tmp = y1;
					y1 = y2;
					y2 = tmp;
					tmpc = code1;
					code1 = code2;
					code2 = tmpc;
				}
				//find the intersections between the line and the viewport edge
				if (x1 != x2)
				m = (y2-y1)/(x2-x1);
				if ((code1 & LEFT) != 0) {
					y1 += (vp.left - x1) * m;
					x1 = vp.left;
				}
				else if ((code1 & RIGHT) != 0) {
					y1 += (vp.right - x1) * m;
					x1 = vp.right;
				}
				else if ((code1 & TOP) != 0) {
					if (x1 != x2)
						x1 += (vp.top - y1) / m;
					y1 = vp.top;
				}
				else if ((code1 & BOTTOM) != 0) {
					if (x1 != x2)
						x1 += (vp.bottom - y1) / m;
					y1 = vp.bottom;
				}
			}
	}
	if (draw) {
		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 (x < left)
			result = result | LEFT;
		else if (x > right)
			result = result | RIGHT;
		if (y > top)
			result = result | TOP;
		else if (y < bottom)
			result = result | BOTTOM;

		return result;
    }
}





