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

public class InterpolatedTriangle2D extends Triangle2D implements Drawable {
    
  protected boolean isUniform;
  protected double scale; 
  //protected int alpha[];
  //protected int red[]; 
  //protected int green[];
  //protected int blue[];
  protected float alpha[];
  protected float red[]; 
  protected float green[];
  protected float blue[];

  ///////  CONSTRUCTORS /////////////////////////////  
  
  // zero argument constructor for future expansion 
  public InterpolatedTriangle2D() {;}

  
  // constructor using three Vertex2D 
  public InterpolatedTriangle2D( Vertex2D v0,  Vertex2D v1,  Vertex2D v2 ) {
    super(v0, v1, v2);
  //   System.out.println( "v0x=" +v[0].getx() + "v0y=" +v[0].gety() + "v0argb=" +v[0].getargb() );
//    System.out.println( "v1x=" +v[1].getx() + "v1y=" +v[1].gety() + "v1argb=" +v[1].getargb() );
//    System.out.println( "v2x=" +v[2].getx() + "v2y=" +v[2].gety() + "v2argb=" +v[2].getargb() );
    
    //check if all vertices are the same color
    isUniform = (v[0].getargb() == v[1].getargb()) && (v[0].getargb() == v[2].getargb() );
    //Scale is always non zero and positive. This zero
    //value indicates that it has not been computed yet
    scale = -1;
    //alpha = new int[3];   
    // red = new int[3];   
    //green = new int[3];
    //blue = new int[3];
    alpha = new float[3];     red = new float[3];   
    green = new float[3];     blue = new float[3];
  }	
  
  /////////  METHODS  ////////////////////////////
 
 
  protected boolean interpolatedTriangleSetup(Raster r) {
      //System.out.println("IN INTERPOLATEDTRIANGLESETP(RASTER)" );
    if( !super.triangleSetup(r)) return false;
    int t0 = v[0].getargb();
    int t1 = v[1].getargb();
    int t2 = v[2].getargb();
    //System.out.println("COLOR INTERPOL");
    //System.out.println("BLUE");
    planeEqn(blue, t0 & 255, t1 & 255, t2 & 255);
    t0 >>= 8;   t1 >>= 8;   t2 >>= 8;
    //System.out.println("GREEN");
    planeEqn(green, t0 & 255, t1 & 255, t2 & 255);
    t0 >>= 8;   t1 >>= 8;   t2 >>= 8;
    //System.out.println("RED");
    planeEqn(red, t0 & 255, t1 & 255, t2 & 255);
    t0 >>= 8;   t1 >>= 8;   t2 >>= 8;
    //System.out.println("ALPHA");
    planeEqn(alpha, t0 & 255, t1 & 255, t2 & 255);
    //System.out.println( " green0=" + green[0] +" green1=" +green[1]+ "green[2] =" + green[2] );         

    
    return true;
  }
  



  public void draw( Raster r) {
      //     System.out.println("IN INTERPOLATEDTRIANGLE.DRAW(RASTER)" );
//       if( isUniform ) {
// 	  System.out.println("IN ISUNIFORM => SUPER.DRAW" );	
// 	  super.draw(r);
// 	  return;
//       }
    

    if( ! this.interpolatedTriangleSetup(r) ){
	for(int i=0; i<3; i++) edge[i].drawLine(r, alpha, red, green, blue);
	return;
    }

    //      if( isPointInside(133.f,250.f) )
    //System.out.println("THIS POINT IN TRI NO" );    

    if( noseNegY >= 0){
      getActiveEdges();
      drawSpan( activeEdge, v[ getVertexNo(noseNegY) ], v[ getVertexNo(noseNegY-1) ], r );
    }
    if( nosePosY >= 0){
      getActiveEdges(); 
      drawSpan( activeEdge, v[ getVertexNo(nosePosY+1) ], v[ getVertexNo(nosePosY) ], r ); 
    }
    if( ltBreak >= 0){
      getActiveEdges(true);
      drawSpan( activeEdge, v[ getVertexNo(ltBreak+1) ], v[ getVertexNo(ltBreak) ], r );
      getActiveEdges(false);
      drawSpan( activeEdge, v[ getVertexNo(ltBreak) ], v[ getVertexNo(ltBreak-1) ], r );
    }
    if( rtBreak >= 0){
      getActiveEdges(true);
      drawSpan( activeEdge, v[ getVertexNo(rtBreak-1) ], v[ getVertexNo(rtBreak) ], r );
      getActiveEdges(false);
      drawSpan( activeEdge, v[ getVertexNo(rtBreak) ], v[ getVertexNo(rtBreak+1) ], r );
    }

  }//DRAW




  protected void drawSpan( int[] aE, Vertex2D vStart, Vertex2D vFinish, Raster r) {
      //System.out.println("IN INTERPOLATEDTRIANGLE.DRAWSPAN......" );
    int pix;
    int aE0 = aE[0];    int aE1 = aE[1]; 
    //System.out.println( " ae0=" + aE0 +" aE1=" + aE1 );
    int stepXFloor = edge[aE0].stepx;
    int stepXCeil = edge[aE1].stepx;
    int x, y;
    y = (int)(vStart.gety()+0.5);
    int yFinish = (int)(vFinish.gety()+0.5);
    //System.out.println( " yStart=" + y +" yFinish=" + yFinish ); 

    while( y <= yFinish ) {
      int xFloor = (int)( -( (edge[aE0].getC()+(edge[aE0].getB() *(float)y)  )/ (edge[aE0].getA()) ) + 0.5 );
      int xCeil = (int)( -( (edge[aE1].getC()+(edge[aE1].getB() *(float)y)  )/ (edge[aE1].getA()) ) );
      //System.out.println( " y=" + y +"*************" ); 
      //System.out.println( "xFloor =" + xFloor +"xCeil =" + xCeil ); 
      for( x=xFloor; x<=xCeil; x++ ) {
	pix = setColor(x,y);
	if( (x<120)&&(y>202)&&(y<212)){
	    System.out.println( "DRAWING THIS UNNECESARYT LINE" );    
	}
	//System.out.println( " x=" + x +" y=" + y +  " pix=" + pix   );
	r.setPixel( pix, x, y);
      }
      y++;
    }

  }//DRAWSPAN



  //protected void planeEqn(int eqn[], int p0, int p1, int p2){
  protected void planeEqn(float eqn[], int p0, int p1, int p2){
      //System.out.println("IN PLANE EQN" );
    //int Ap, Bp, Cp;
    float Ap, Bp, Cp;
    if (scale <= 0) {
      //scale = (1 << EdgeEqn.FRACBITS) / ((double) twiceArea);
      scale = (double)1. / ((double) twiceArea);
    }
    //System.out.println( "p0 =" + p0 +  "p1 =" + p1+"p2 =" + p2); 
    double sp0 = scale * p0;
    double sp1 = scale * p1;
    double sp2 = scale * p2;
    //System.out.println( "sp0 =" + sp0 +  "sp1 =" + sp1+"sp2 =" + sp2);
    //System.out.println( "A2=" + edge[2].getA() +" A0=" + edge[0].getA() + " A1=" + edge[1].getA());
    //System.out.println( "B2=" + edge[2].getB() +" B0=" + edge[0].getB() + " B1=" + edge[1].getB());
    //System.out.println( "C2=" + edge[2].getC() +" C0=" + edge[0].getC() + " C1=" + edge[1].getC());


 
   //Ap = (int)(edge[2].getA()*sp2 + edge[0].getA()*sp0 + edge[1].getA()*sp1);
   //Bp = (int)(edge[2].getB()*sp2 + edge[0].getB()*sp0 + edge[1].getB()*sp1);
   //Cp = (int)(edge[2].getC()*sp2 + edge[0].getC()*sp0 + edge[1].getC()*sp1);
    Ap = (float)(edge[2].getA()*sp2 + edge[0].getA()*sp0 + edge[1].getA()*sp1);
    Bp = (float)(edge[2].getB()*sp2 + edge[0].getB()*sp0 + edge[1].getB()*sp1);
    Cp = (float)(edge[2].getC()*sp2 + edge[0].getC()*sp0 + edge[1].getC()*sp1);
    eqn[0] = Ap;
    eqn[1] = Bp;
    //eqn[2] = Ap*xMin + Bp*yMin + Cp + (1 << (EdgeEqn.FRACBITS - 1));
    eqn[2] =  Cp;
    //System.out.println( "scale =" + scale +"Ap =" + Ap + "Bp =" + Bp+"Cp =" + Cp); 
    return;
  }
  

  protected int setColor(int x, int y) {
    //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) );
  }


    public void drawLine( Raster r ){;}
    public void drawLine( Raster r, float[] alpha, float[] red,  float[] green,  float[] blue) {;}




} // CLASS INTERPOLATEDTRIANGLE2D
