import java.awt.*;
import java.lang.*;

public class EdgeEqn implements Drawable{
  
    //protected int A, B, C;     //a vs A
  protected float A, B, C;     //a vs A
  protected Vertex3D v[];    
  //public final static int FRACBITS = 12;
  protected int flag;       //to sort vertices in x and y  
  protected float slope;
  public boolean horiz; //if edge is horiz
  private int edgeNo;

  //the below are used only in rendering
  private boolean isInterpolated;
  protected float alpha[];
  protected float red[]; 
  protected float green[];
  protected float blue[];

  int h, w; //raster's dimensiions will be set in draw

  ///////  CONSTRUCTORS /////////////////////////////  
  
  // constructor using Vertex3D and edge no.
  public EdgeEqn( int eNo, Vertex3D v0, Vertex3D v1  ) {
//       System.out.println("CONSTRUCTING EDGEEQN" );
    edgeNo = eNo;
    v = new Vertex3D[2];
    v[0]=v0;
    v[1]=v1;
    
    //the below are all in ints - use floats later
    A = v[0].getCoord(1) -  v[1].getCoord(1);
    B = v[1].getCoord(0) -  v[0].getCoord(0); 
    //C =  v[0].getCoord(0)*v[1].getCoord(1) -  v[1].getCoord(0)* v[0].getCoord(1) ;
    C = -0.5f * (A*(v[0].getCoord(0)+v[1].getCoord(0)) + B*(v[0].getCoord(1)+v[1].getCoord(1)) );
    flag = 0;
    if(A>=0) flag +=8;  //A=0 doesn't make sense for floats
    if(B>=0) flag +=1; //can be used for degenerate tris (coincident lines,pts)
    if( findSlope() ){
      if( slope>0.) { 

      }
      if( slope<0.) {

      }
    }
    else {

    }
  }	
  

  /////////  METHODS  ////////////////////////////
  
  private boolean findSlope(){
      //if( (int)((v[1].getCoord(0)+0.5)<<12) == (int)((v[0].getCoord(0)+0.5)<<12)) return false;
      //if( (int)((v[1].getCoord(1)+0.5)<<12) == (int)((v[0].getCoord(1)+0.5)<<12)) {
      if( (int)((v[1].getCoord(0)+0.5)) == (int)((v[0].getCoord(0)+0.5))) return false;
      if( (int)((v[1].getCoord(1)+0.5)) == (int)((v[0].getCoord(1)+0.5))) {
      slope=0;
      horiz = true;
      return true;
    }
    //slope = (float)(v[1].getCoord(1)-v[0].getCoord(1))/(float)(v[1].getCoord(0)-v[0].getCoord(0)); 
    slope = -A/B; 
    horiz = false;
    return true;
  }

  public float evaluateAt( int x, int y) {
    return (A*x+B*y+C);
  }

   public float evaluateAt( float x, float y) {
    return (A*x+B*y+C);
  }

  //USED WHEN CONVERTING CLOCKWISE TO COUTNERCLOCKCWISE
  public void reSet( int eNo, Vertex3D v0, Vertex3D v1 ) {
    edgeNo = eNo;
    v[0] = v0;
    v[1] = v1;
    //the below are all in ints - use floats later
    A = v[0].getCoord(1) -  v[1].getCoord(1);
    B = v[1].getCoord(0) -  v[0].getCoord(0); 
    C = -0.5f * (A*(v[0].getCoord(0)+v[1].getCoord(0)) + B*(v[0].getCoord(1)+v[1].getCoord(1)) );
    flag = 0;
    if(A>=0) flag +=8;  //A=0 doesn't make sense for floats
    if(B>=0) flag +=1; //can be used for degenerate tris (coincident lines,pts)
    if( findSlope() ){
      if( slope>0.) { 
      }
      if( slope<0.) {
      }
    }
    else {
    }
  }
 
 public void setEdgeNo( int someNo) {
   edgeNo = someNo;
  }
 
 public int getEdgeNo() {
   return edgeNo;
  }

 public float getA() {
   return A;
  }
 
  public float getB() {
   return B;
  }

  public float getC() {
   return C;
  }

  public void flip() {
    A = -A; B = -B; C = -C;
  }
     
  public int getVertexNo( int edgeVertexNo) {
   return v[edgeVertexNo].getVertexNo();
  }
 

     
  public void drawLine( Raster r, float[] alpha, float[] red,  float[] green,  float[] blue) {
	//System.out.println("IN DRAWLINE INTERP0L" );
	if((Math.abs(A)<=0.5) && (Math.abs(B)<=0.5)  ){
	    //System.out.println("IN DRAWLINE INTERP0L - VERTEX" );
	    v[0].draw(r);
	    return;
	}
	//this.alpha = new float[3]; 
	//this.red = new float[3];   
	//this.green = new float[3];
	//this.blue = new float[3];
	this.alpha  = alpha ;
	this.red    = red ;
	this.green  = green ;
	this.blue  =  blue;
	isInterpolated = true;
	draw(r);
	return;
    }


    public void drawLine( Raster r ) {
	if( (Math.abs(A)<=0.5) && (Math.abs(B)<=0.5) ){
	    //System.out.println("IN DRAWLINE FLAT - VERTEX" );
	    v[0].draw(r);
	    return;
	}
	isInterpolated = false;
	draw(r);
	return;
    }


    protected int setColor(int x, int y) {
	if(isInterpolated ) {
	    //int ca = alpha[0]*x + alpha[1]*y + alpha[2];
	    //int cr = red[0]*x + red[1]*y + red[2];
	    //int cg = green[0]*x + green[1]*y + green[2];
	    //int cb = blue[0]*x + blue[1]*y + blue[2];
	    int ca = Math.round(alpha[0]*x + alpha[1]*y + alpha[2] );
	    int cr = Math.round(red[0]*x + red[1]*y + red[2] );
	    int cg = Math.round(green[0]*x + green[1]*y + green[2] );
	    int cb = Math.round(blue[0]*x + blue[1]*y + blue[2] );
	    return( (ca<<24)|(cr<<16)|(cg<<8)|(cb) );
	}
	else {
	    return( v[0].getColor() );
	}
    }


    public void draw( Raster r) {
	//System.out.println("IN EDGE.DRAW => DRAWING LINE NOT VERTEX" );	
        h=r.getHeight(); w = r.getWidth();
	float dy= -A; float dx = B; 
	int x, y;
	int x0=(int)(v[0].getCoord(0)+0.5); int y0=(int)(v[0].getCoord(1)+0.5);
	int x1=(int)(v[1].getCoord(0)+0.5); int y1=(int)(v[1].getCoord(1)+0.5);
	r.setPixel( setColor(x0,y0), x0, y0);
	float t = (float) 0.5; 
	if (Math.abs(dx) > Math.abs(dy)) {          // slope < 1
	    float m =  dy / dx;      // compute slope
	    t += y0;
	    int stepx = (dx < 0) ? -1 : 1;
	    m *= stepx;
	    while (x0 != x1) {
		x0 += stepx;                           // step to next x value
		t += m;                             // add slope to y value
		y= (int) t;
		if (x0 >= 0 && y >= 0 && x0 < w && y < h){
		  r.setPixel(setColor(x0,y), x0, y);
		}
	    }
	} else {                                    // slope >= 1
	    float m = dx /  dy;      // compute slope
	    t += x0;
	    int stepy = (dy < 0) ? -1 : 1;
	    m *= stepy;
	    while (y0 != y1) {
		y0 += stepy;                           // step to next y value
		t += m;                             // add slope to x value
		x = (int) t;
		if (x >= 0 && y0 >= 0 && x < w && y0 < h){
		  r.setPixel(setColor(x,y0), x, y0);
		}
	    }
	}
	
    }
    
    public void draw( Raster r, Buffer buf){;}

    public boolean isPointInPosHalfPlane(Vertex3D v){
	if( evaluateAt(v.getCoord(0), v.getCoord(1))>= 0)return true;
	else return false;
    }


    public float findXAtGivenY( float y){
	float x = -(C+B*y)/A;
	return x;

    }



} // CLASS EDGEEQN
