import Targa.*;
import util.*;
import java.util.Vector;
import java.io.*;

/** This class is identical to the clinical-view Colour1.java.
*/
public class Colour1 {
  TargaPicture tp;
  PrintWriter log;
  final boolean LESION = true;
  final boolean SKIN = false;
  int boxSize;


  ///----------------------------------------------------
	public Colour1(TargaPicture t, PrintWriter logFile, int boxSize) {
    this.tp = t;
    this.log = logFile;
    this.boxSize = boxSize;

  }



  ///----------------------------------------------------
	public void getColourAttributes() {
		int skinCount = 0; int tumorCount = 0;

		double rTumorVar=0, gTumorVar=0, bTumorVar=0, lumTumorVar =0 ;
		double rTumorAv=0, gTumorAv=0, bTumorAv=0, lumTumorAv =0;
		double rSkinAv=0, gSkinAv=0, bSkinAv =0;

		double lTumorAv=0, alphaTumorAv=0, betaTumorAv =0; // Spherical colour coords
		double lTumorVar=0, alphaTumorVar=0, betaTumorVar =0; // Spherical colour coords
		double lSkinAv=0, alphaSkinAv=0, betaSkinAv =0; // Spherical colour coords

		double LxTumorAv=0,axTumorAv=0,bxTumorAv =0;          // L* a* b*
		double LxTumorVar=0,axTumorVar=0,bxTumorVar =0;       // L* a* b*
		double LxSkinAv=0,axSkinAv=0,bxSkinAv =0;             // L* a* b*

    double hueTumorAv = 0, hueSkinAv = 0;
    double cxTumorAv = 0, cxSkinAv = 0;
    double hueTumorVar = 0, hueSkinVar = 0;
    double cxTumorVar = 0, cxSkinVar = 0;

		double relChromRed, relChromGreen, relChromBlue ;

		float r,g,b;

		RGBPoint pt = null;

		for (int y = 0; y < tp.h;y++) {
			for (int x = 0; x < tp.w; x++) {
      pt = new RGBPoint(tp.getImageData(x,y)) ;
	pt.calcLAB() ;
	pt.calcSpherical();

	if (tp.getMaskData(x,y) == true) {
      rTumorAv += pt.r;
      gTumorAv += pt.g;
      bTumorAv += pt.b;
      lTumorAv += pt.L;
      alphaTumorAv += pt.alpha;
      betaTumorAv += pt.beta;


      LxTumorAv += pt.Lx;
      axTumorAv += pt.ax;
      bxTumorAv += pt.bx;
      cxTumorAv += pt.Cx;
      hueTumorAv += pt.hue;
	tumorCount++ ;
	} else {
		if (pt.r != 0 || pt.g != 0 || pt.b !=0) {
		 rSkinAv += pt.r;
	      gSkinAv += pt.g;
	      bSkinAv += pt.b;
	      lSkinAv += pt.L;
	      alphaSkinAv += pt.alpha;
	      betaSkinAv += pt.beta;
	      LxSkinAv += pt.Lx;
	      axSkinAv += pt.ax;
	      bxSkinAv += pt.bx;
	      cxSkinAv += pt.Cx;
	      hueSkinAv += pt.hue;
	
    		skinCount++ ;	
		    }
	}
	}
	}	

    rTumorAv /= tumorCount;
    gTumorAv /= tumorCount;
    bTumorAv /= tumorCount;
    lTumorAv /= tumorCount;
    alphaTumorAv /= tumorCount;
    betaTumorAv /= tumorCount;
    LxTumorAv /= tumorCount;
    axTumorAv /= tumorCount;
    bxTumorAv /= tumorCount;
    cxTumorAv /= tumorCount;
    hueTumorAv /= tumorCount;

    rSkinAv /= skinCount;
    gSkinAv /= skinCount;
    bSkinAv /= skinCount;
    lSkinAv /= skinCount;
    alphaSkinAv /= skinCount;
    betaSkinAv /= skinCount;
    LxSkinAv /= skinCount;
    axSkinAv /= skinCount;
    bxSkinAv /= skinCount;
    cxSkinAv /= skinCount;
    hueSkinAv /= skinCount;




    ///----------------- Variance calculation
	int size = tp.w*tp.h;
    for (int i = 0; i < size; i++) {
      pt = new RGBPoint(tp.getImageData(i)) ;
	if (tp.getMaskData(i)==true) {
	pt.calcLAB() ;
	pt.calcSpherical();

      rTumorVar += (pt.r-rTumorAv)*(pt.r-rTumorAv);
      gTumorVar += (pt.g-gTumorAv)*(pt.g-gTumorAv);
      bTumorVar += (pt.b-bTumorAv)*(pt.b-bTumorAv);
      lTumorVar += (pt.L-lTumorAv)*(pt.L-lTumorAv);
      alphaTumorVar += (pt.alpha-alphaTumorAv)*(pt.alpha-alphaTumorAv);
      betaTumorVar += (pt.beta-betaTumorAv)*(pt.beta-betaTumorAv);
      LxTumorVar += (pt.Lx-LxTumorAv)*(pt.Lx-LxTumorAv);
      axTumorVar += (pt.ax-axTumorAv)*(pt.ax-axTumorAv);
      bxTumorVar += (pt.bx-bxTumorAv)*(pt.bx-bxTumorAv);
      cxTumorVar += (pt.Cx-cxTumorAv)*(pt.Cx-cxTumorAv);
      hueTumorVar += (pt.hue-hueTumorAv)*(pt.hue-hueTumorAv);
	}
    }
    rTumorVar /= tumorCount;
    gTumorVar /= tumorCount;
    bTumorVar /= tumorCount;
    lTumorVar /= tumorCount;
    alphaTumorVar /= tumorCount;
    betaTumorVar /= tumorCount;
    LxTumorVar /= tumorCount;
    axTumorVar /= tumorCount;
    bxTumorVar /= tumorCount;
    cxTumorVar /= tumorCount;
    hueTumorVar /= tumorCount;

 		relChromRed = rTumorAv/(rTumorAv+gTumorAv+bTumorAv) - rSkinAv/(rSkinAv+gSkinAv+bSkinAv) ;
		relChromGreen = gTumorAv/(rTumorAv+gTumorAv+bTumorAv) - gSkinAv/(rSkinAv+gSkinAv+bSkinAv) ;
		relChromBlue = bTumorAv/(rTumorAv+gTumorAv+bTumorAv) - bSkinAv/(rSkinAv+gSkinAv+bSkinAv) ;

    log.print(rTumorAv + "\t" + gTumorAv + "\t" + bTumorAv + "\t" );
    log.print(lTumorAv + "\t" + alphaTumorAv + "\t" + betaTumorAv + "\t");
    log.print(LxTumorAv + "\t" + axTumorAv + "\t" + bxTumorAv + "\t");
    log.print(cxTumorAv + "\t" + hueTumorAv+ "\t");

    log.print((rSkinAv-rTumorAv) + "\t" + (gSkinAv-gTumorAv) + "\t" + (bSkinAv-bTumorAv) + "\t");
    log.print((lSkinAv-lTumorAv) + "\t" + (alphaSkinAv-alphaTumorAv) + "\t" + (betaSkinAv-betaTumorAv) + "\t");
    log.print((LxSkinAv-LxTumorAv) + "\t" + (axSkinAv-axTumorAv) + "\t" + (bxSkinAv-bxTumorAv) + "\t");
    log.print((cxSkinAv-cxTumorAv) + "\t" + (hueSkinAv-hueTumorAv) + "\t" );

    log.print(rTumorVar + "\t" + gTumorVar + "\t" + bTumorVar + "\t" );
    log.print(lTumorVar + "\t" + alphaTumorVar + "\t" + betaTumorVar + "\t");
    log.print(LxTumorVar + "\t" + axTumorVar + "\t" + bxTumorVar + "\t");
    log.print(cxTumorVar + "\t" + hueTumorVar + "\t");

    log.println(relChromRed + "\t" + relChromGreen + "\t" + relChromBlue + "\t");
    log.flush();

	}





  ///----------------------------------------------------
	RGBPoint getMedianColour(int x, int y, int wid, boolean lesionOrSkin) {
		RGBPoint pt = null;
    RGBPoint[] colour = new RGBPoint[wid*wid];
    float[]rgbDistance = new float[wid*wid];
    float[]lAlphaBetaDistance = new float[wid*wid];
    float[] lxAxBxDistance = new float[wid*wid];

    int count = 0;
    double[] temp = null;
   	for (int i =0; i< wid; i++) {
	  	for (int j =0; j< wid; j++) {
        if (tp.getMaskData(x+j,y+i) == lesionOrSkin) {
          try {
   			  	pt = new RGBPoint(tp.getImageData(x+j,y+i));
          } catch (ArrayIndexOutOfBoundsException e) {
            continue ;
          }
          if (pt != null && pt.r > 0) {
            pt.calcLAB();
            temp = pt.getSphericalCoords() ;
            rgbDistance[count] = (float)Distance.getEuclidDistance(0,0,0,pt.r,pt.g,pt.b);
   			  	lxAxBxDistance[count] = (float)Distance.getEuclidDistance(0,0,0,pt.Lx,pt.ax,pt.bx);
  				  lAlphaBetaDistance[count] = (float)Distance.getEuclidDistance(0,0,0,temp[0],temp[1],temp[2]);

            colour[count] = pt;
            count ++;
          }
        }
      }
    }

	  RGBPoint rgbMedianColour = (RGBPoint)Median.getMedianValue(colour,rgbDistance, count);
    RGBPoint lxAxBxMedianColour = (RGBPoint)Median.getMedianValue(colour,lxAxBxDistance, count);
    RGBPoint lAlphaBetaMedianColour = (RGBPoint)Median.getMedianValue(colour, lAlphaBetaDistance, count);
    lxAxBxMedianColour.calcLAB();
    lAlphaBetaMedianColour.calcSpherical();
    rgbMedianColour.Lx = lxAxBxMedianColour.Lx;
    rgbMedianColour.ax = lxAxBxMedianColour.ax;
    rgbMedianColour.bx = lxAxBxMedianColour.bx;
    rgbMedianColour.Cx = lxAxBxMedianColour.Cx;
    rgbMedianColour.hue = lxAxBxMedianColour.hue;
    rgbMedianColour.L = lAlphaBetaMedianColour.L;
    rgbMedianColour.alpha = lAlphaBetaMedianColour.alpha;
    rgbMedianColour.beta = lAlphaBetaMedianColour.beta;

    for (int i =0; i< wid; i++) {
	  	for (int j =0; j< wid; j++) {
        if (lesionOrSkin == LESION) {
          tp.setImageData(x+j,y+i,rgbMedianColour.toInt());
        }
      }
    }
    
		return rgbMedianColour;
	}




	public static void main(String []args) {
    int boxSize = 1;
    if (args[0].equals("iterate") == true) {
  		Vector v = new Vector() ;
		  FileReader fr = null;
  		StreamTokenizer st = null;
      int numberOfFiles = 0;
      String dir1=null, dir2=null, file = null;

      boxSize = new Integer(args[3]).intValue() ;
System.out.println("Colour (clinical view) analysis. BoxSize:"+boxSize);
	  	try {
		  	fr = new FileReader(args[1]) ;
			  st = new StreamTokenizer(fr) ;
        st.slashStarComments(true);
  			st.nextToken() ;
        numberOfFiles = (int)st.nval;

  			st.nextToken() ;
        dir1 = (String)st.sval;
  			st.nextToken() ;
        dir2 = (String)st.sval;

		  	for (int i = 0; i < numberOfFiles; i++) {
			  	st.nextToken() ;
				file=new Integer((int)st.nval).toString();
				st.nextToken() ;
				if (st.sval != null) file+=st.sval;
				else st.pushBack();
System.out.println(file);
  				v.addElement(file) ;
			  }
  		} catch (IOException e) {
System.out.println("Read Error in Specification File: ACTION: EXIT") ;
System.exit(1);
	  	}

      // Create log stream
      FileWriter fw = null;
      PrintWriter logFile = null;
      try {
        fw = new FileWriter(args[2]) ;
        logFile = new PrintWriter(fw, true);
      } catch (IOException e) {
System.out.println("Error opening Log File: ACTION: Use System.out") ;
        // true turns automatic flushing on, so every println causes something to print
        logFile = new PrintWriter(System.out, true) ;
      }

      String tgaFile = null;
      String maskFile = null;
logFile.print("File \t rTumorAv \t gTumorAv \t bTumorAv \t");
logFile.print("lTumorAv \t alphaTumorAv \t betaTumorAv \t");
logFile.print("LxTumorAv \t axTumorAv \t bxTumorAv \t");
logFile.print("cxTumorAv \t hueTumorAv \t");


logFile.print("rAvgDf \t gAvgDf \t bAvgDf \t");
logFile.print("lAvgDf \t alphaAvgDf \t betaAvgDf \t");
logFile.print("LxAvgDf \t axAvgDf \t bxAvgDf \t");
logFile.print("CxAvgDf \t hueAvgDf \t ");

logFile.print("rTumorVar \t gTumorVar \t bTumorVar \t");
logFile.print("lTumorVar \t alphaTumorVar \t betaTumorVar \t");
logFile.print("LxTumorVar \t axTumorVar \t bxTumorVar \t");
logFile.print("cxTumorVar \t hueTumorVar \t");

logFile.println("relChromRed \t relChromGreen \t relChromBlue \t");
      Colour1 c ;
      for (int i = 0; i < numberOfFiles; i++) {
    		try {
          tgaFile =dir1+((String)v.elementAt(i))+".tga";
          maskFile = dir2+((String)v.elementAt(i))+".msk";
    			TargaPicture tp = new TargaPicture(tgaFile) ;
			    tp.read() ;
    			tp.readMask(maskFile);
    logFile.print(((String)v.elementAt(i))+ "\t");

          c = new Colour1(tp, logFile, boxSize) ;
		    	c.getColourAttributes() ;
    		} catch (IOException e) {
System.out.println("Error reading file:");
    		}
      } // End for
    } // end if

    else {
  		try {
        boxSize = new Integer(args[2]).intValue() ;

		  	TargaPicture tp = new TargaPicture(args[0]) ;
	  		tp.read() ;
			  tp.readMask(args[1]);
  			Colour1 c = new Colour1(tp, new PrintWriter(System.out, true), boxSize);
        c.getColourAttributes() ;
	  	} catch (IOException e) {
System.out.println("Error " +e);
		  }
  	}
  }
}