package endu;

import vtk.*;
import battery.graph.GraphPanel;

public class util {	
	public static double[] multiplyMatrix(double array[][], double array1[]) {
		double array2[] = new double[3];
		array2[0]=array[0][0]*array1[0]+ array[0][1]*array1[1]+ array[0][2]*array1[2];
		array2[1]=array[1][0]*array1[0]+ array[1][1]*array1[1]+ array[1][2]*array1[2];
		array2[2]=array[2][0]*array1[0]+ array[2][1]*array1[1]+ array[2][2]*array1[2];		       
		return array2;
	}

	public static double getMax(vtkFloatArray array) {
		double max = Double.NEGATIVE_INFINITY;
		for (int i=0; i<ReadCSV.numRow; i=i+1){
	    	if (max<array.GetValue(i)){
	    		max = array.GetValue(i);
	    	}
	    }
		return max;
	}
	public static double getMin(vtkFloatArray array) {
		double min = Double.POSITIVE_INFINITY;
		for (int i=0; i<ReadCSV.numRow; i=i+1){
	    	if (min > array.GetValue(i)&& array.GetValue(i) != EnduModel.missingValue){
	    		min = array.GetValue(i);
	    	}
	    }
		return min;
	}
	
	public static int isMeasureUsed(int measure) {
		for (int color=0; color<11; color++){
			if (EnduModel.colorMeasure[color]==measure){
				return color;
			}
		}
		return -1;
	}
	
	public static void updateVTK() {	
		EnduModel.renWin.repaint();
		EnduModel.renWin.UpdateLight();
	}
	public static void updateControllers() {
		double[] vector = EnduModel.camera.GetPosition();// new
		GraphPanel.cameraX.setValue(vector[0]);
		GraphPanel.cameraY.setValue(vector[1]);
		GraphPanel.cameraZ.setValue(vector[2]);
		if (vector[2]<0) {
			EnduModel.ren.SetBackground(1,1,0.8);
		}
		else{
			EnduModel.ren.SetBackground(0.8,0.8,1);
		}
	}
	public static void rescaleDepth() {
		 for (int i=1; i<Math.max(util.getMax(ReadCSV.arrayX),util.getMax(ReadCSV.arrayY));i++){	    	
			 EnduModel.ren.RemoveActor(EnduModel.zTextActor[i]);
		 }	 
		 EnduModel.createTextDepth();
	}
	public static void rescaleXY() {
		 for (int i=1; i<Math.max(util.getMax(ReadCSV.arrayX),util.getMax(ReadCSV.arrayY));i++){	    	
			 EnduModel.ren.RemoveActor(EnduModel.xTextActor[i]);
			 EnduModel.ren.RemoveActor(EnduModel.yTextActor[i]);
		 }	 
		 EnduModel.ren.RemoveActor(EnduModel.planeActor);
		 EnduModel.createImage();
		 EnduModel.createTextXY();
	}
	
	public static void repaintVTK() {
		for (int m=0; m<8;m++){
			if (util.isMeasureUsed(m)>=0){
				removeVTK(m);
			}
		}	
		for (int m=0; m<8;m++){
			if (util.isMeasureUsed(m)>=0){
				int color= util.isMeasureUsed(m);
				addVTK(m,color);
			}
		}	
	}
	
	public static void removeVTK(int m) {
		for (int i=0; i<ReadCSV.numRow; i=i+EnduModel.dataReduction1){
		    EnduModel.ren.RemoveActor(EnduModel.actorArray[m][i] );
		}	
		removeLegend(m);
	}
	
	public static void addVTK(int measure, int color) {
		
		double min = util.getMin(ReadCSV.arrayMeasure[measure]);
		double max = util.getMax(ReadCSV.arrayMeasure[measure]);
		for (int i=0; i<ReadCSV.numRow; i=i+EnduModel.dataReduction2){
	    	vtkSphereSource s = new vtkSphereSource();
	    	s.SetRadius(EnduModel.radius);
	        s.SetCenter(ReadCSV.arrayY.GetValue(i)/EnduModel.scaleXY + EnduModel.radius*EnduModel.measureSlot[measure],
	        			ReadCSV.arrayX.GetValue(i)/EnduModel.scaleXY,ReadCSV.arrayDepth.GetValue(i)/EnduModel.scaleDepth);  
	        vtkPolyDataMapper sphereMapper = new vtkPolyDataMapper();
	        sphereMapper.SetInputConnection( s.GetOutputPort() );
	        EnduModel.actorArray[measure][i] = new vtkActor();
	        EnduModel.actorArray[measure][i].SetMapper(sphereMapper );

	    	double saturation = 0;
	    	if (ReadCSV.arrayMeasure[measure].GetValue(i) == EnduModel.missingValue){
	    		saturation = 1;
	    		EnduModel.actorArray[measure][i].GetProperty().SetColor(0, 0, 0);
	    	}
	    	else{
	    		saturation = (max-ReadCSV.arrayMeasure[measure].GetValue(i))/(max-min);
	    		double[] rgb= getRGB(measure, color, saturation); 
	    		EnduModel.actorArray[measure][i].GetProperty().SetColor(rgb[0],rgb[1],rgb[2]);
	    		
	    	}
	    	EnduModel.ren.AddActor( EnduModel.actorArray[measure][i] );
	    }
		createLegend(measure, color);
	}
	

	public static void removeMeasure(int color) {
		System.out.println("");
		System.out.println("REMOVEMeasure color: "+color);
		if (color<0) return;
		
		int m = EnduModel.colorMeasure[color];
		System.out.println("m: "+m);
		if (m<0)return;
		
		int slot = EnduModel.measureSlot[m];
		EnduModel.measureSlot[m]=-1;	
		EnduModel.slotMeasure[slot]=-1;                      
		EnduModel.colorMeasure[color]=-1;                      
		
		for (int i=0; i<ReadCSV.numRow; i=i+EnduModel.dataReduction1){
		    EnduModel.ren.RemoveActor(EnduModel.actorArray[m][i] );
	    }
		removeLegend(m);
	}
			
	public static void addMeasure(int measure, int color) {
		System.out.println("");
		System.out.println("addMeasure color: "+color + " measure: "+measure);			
		System.out.println("EnduModel.colorMeasure[color]: "+EnduModel.colorMeasure[color]);
		
		if (isMeasureUsed(measure)>=0){
			return;
		}
		if (EnduModel.colorMeasure[color]>=0){
			removeMeasure(color);
		}
		
		int firstAvailableSlot =0;
		for (int i=0; i<8; i++){
			if (EnduModel.slotMeasure[i]==-1){
				firstAvailableSlot = i;
				break;
			}
		}
		EnduModel.colorMeasure[color]=measure;
		System.out.println("EnduModel.colorMeasure[color]: "+EnduModel.colorMeasure[color]);
		EnduModel.slotMeasure[firstAvailableSlot]=measure;
		EnduModel.measureSlot[measure]= firstAvailableSlot;
	
		double min = util.getMin(ReadCSV.arrayMeasure[measure]);
		double max = util.getMax(ReadCSV.arrayMeasure[measure]);
		for (int i=0; i<ReadCSV.numRow; i=i+EnduModel.dataReduction2){
	    	vtkSphereSource s = new vtkSphereSource();
	    	s.SetRadius(EnduModel.radius);
	        s.SetCenter(ReadCSV.arrayY.GetValue(i)/EnduModel.scaleXY + EnduModel.radius*EnduModel.measureSlot[measure],
	        			ReadCSV.arrayX.GetValue(i)/EnduModel.scaleXY,ReadCSV.arrayDepth.GetValue(i)/EnduModel.scaleDepth);  
	        vtkPolyDataMapper sphereMapper = new vtkPolyDataMapper();
	        sphereMapper.SetInputConnection( s.GetOutputPort() );
	        EnduModel.actorArray[measure][i] = new vtkActor();
	        EnduModel.actorArray[measure][i].SetMapper(sphereMapper );

	    	double saturation = 0;
	    	if (ReadCSV.arrayMeasure[measure].GetValue(i) == EnduModel.missingValue){
	    		EnduModel.actorArray[measure][i].GetProperty().SetColor(0, 0, 0);
	    	}
	    	else{
	    		saturation = (max-ReadCSV.arrayMeasure[measure].GetValue(i))/(max-min);
	    		double[] rgb= getRGB(measure, color, saturation); 
	    		EnduModel.actorArray[measure][i].GetProperty().SetColor(rgb[0],rgb[1],rgb[2]);
	    	}
	    	EnduModel.ren.AddActor( EnduModel.actorArray[measure][i] );
	    }
		createLegend(measure, color);
	}
	
	public static void removeLegend(int m) {
		  for(int i=0; i<4;i++){
			  EnduModel.ren.RemoveActor(EnduModel.textActor[m][i]);
		  }
		  for(int i=0; i<3;i++){
			  EnduModel.ren.RemoveActor(EnduModel.legendActor[m][i]);
		  }
		    	
		
	}
	public static void createLegend(int m, int color) {
	//Add the actors to the renderer, set the background and size
		int slot = EnduModel.measureSlot[m];
		int yOffset= 35;
		int y= 12;
		int xOffset= 101;
		int xLegend= 60;

		
		  EnduModel.textActor[m][0] = new vtkTextActor();
		//  EnduModel.textActor[m].ScaledTextOn();
		  EnduModel.textActor[m][0].SetDisplayPosition(0,slot*yOffset+yOffset-5+y);
		  EnduModel.textActor[m][0].SetInput(""+ReadCSV.MEASURE[m]);
	      EnduModel.textActor[m][0].GetPosition2Coordinate().SetCoordinateSystemToNormalizedViewport();
		  EnduModel.textActor[m][0].GetPosition2Coordinate().SetValue(0.2, 0.1);

		  vtkTextProperty tprop = EnduModel.textActor[m][0].GetTextProperty();
		  tprop.SetFontSize(16);
		  tprop.SetFontFamilyToArial();
		  tprop.SetJustificationToLeft();
		  tprop.BoldOn();
		  tprop.ItalicOn();
		  tprop.ShadowOn();
		  tprop.SetColor(0, 0, 0);
		  EnduModel.ren.AddActor2D(EnduModel.textActor[m][0]);

		  double min = util.getMin(ReadCSV.arrayMeasure[m]);
		  double max = util.getMax(ReadCSV.arrayMeasure[m]);
		  double average = (max+min)/2;
 	
		  double[] value=new double[3];
		  value[0]= min;
		  value[1]= average;
		  value[2]= max;
		  
		  for(int i=1; i<4;i++){
			  	  EnduModel.textActor[m][i] = new vtkTextActor();
				  EnduModel.textActor[m][i].SetDisplayPosition(xOffset+(xLegend*(i-1)+25),slot*yOffset+yOffset-yOffset/2-2+y);
				  EnduModel.textActor[m][i].SetInput(""+formatDouble(value[i-1]));
			      EnduModel.textActor[m][i].GetPosition2Coordinate().SetCoordinateSystemToNormalizedViewport();
				  EnduModel.textActor[m][i].GetPosition2Coordinate().SetValue(0.2, 0.1);

				  vtkTextProperty tprop2 = EnduModel.textActor[m][i].GetTextProperty();
				  tprop2.SetFontSize(12);
				  tprop2.SetFontFamilyToArial();
				  tprop2.SetJustificationToLeft();
				  tprop2.ItalicOn();
				  tprop2.ShadowOn();
				  tprop2.SetColor(0, 0, 0);
				  EnduModel.ren.AddActor2D(EnduModel.textActor[m][i]);
		  }
		  
		  
		 	  int id = 0; 
              vtkPoints points1 = new vtkPoints(); 
              vtkPoints points2 = new vtkPoints(); 
              vtkPoints points3 = new vtkPoints(); 
              points1.SetNumberOfPoints(2); 
              points2.SetNumberOfPoints(2); 
              points3.SetNumberOfPoints(2); 
              while (id < 2)
              { 
                  if (id==0) {
                	  points1.InsertPoint(id,xOffset,yOffset*slot+yOffset+y , 0);             
                 	  points2.InsertPoint(id,xOffset+xLegend,yOffset*slot+yOffset+y , 0);             
                 	  points3.InsertPoint(id,xOffset+2*+xLegend,yOffset*slot+yOffset+y , 0);             
                  }
                  else{
                	  points1.InsertPoint(id,xOffset+xLegend,yOffset*slot+yOffset+y , 0);               
                 	  points2.InsertPoint(id,xOffset+2*xLegend,yOffset*slot+yOffset+y , 0);             
                 	  points3.InsertPoint(id,xOffset+3*+xLegend,yOffset*slot+yOffset+y , 0);             
                  }
            	  id++; 
              } 
              vtk.vtkCellArray lines1 = new vtk.vtkCellArray(); 
              vtk.vtkCellArray lines2 = new vtk.vtkCellArray(); 
              vtk.vtkCellArray lines3 = new vtk.vtkCellArray(); 
              lines1.Allocate(1, 1); 
              lines1.InsertNextCell(id); 
              lines1.SetNumberOfCells(id); 
              lines2.Allocate(1, 1); 
              lines2.InsertNextCell(id); 
              lines2.SetNumberOfCells(id); 
              lines3.Allocate(1, 1); 
              lines3.InsertNextCell(id); 
              lines3.SetNumberOfCells(id); 

              for (int k = 0; k < id; ++k) {
            	  lines1.InsertCellPoint(k);
            	  lines2.InsertCellPoint(k);
            	  lines3.InsertCellPoint(k);
            	  
              }

              vtkPolyData c_polyData1 = new vtkPolyData(); 
              c_polyData1.ReleaseDataFlagOn(); 
              c_polyData1.Allocate(1, 1); 
              c_polyData1.SetPoints(points1); 
              c_polyData1.SetLines(lines1); 
              vtkPolyData c_polyData2 = new vtkPolyData(); 
              c_polyData2.ReleaseDataFlagOn(); 
              c_polyData2.Allocate(1, 1); 
              c_polyData2.SetPoints(points2); 
              c_polyData2.SetLines(lines2); 
              vtkPolyData c_polyData3 = new vtkPolyData(); 
              c_polyData3.ReleaseDataFlagOn(); 
              c_polyData3.Allocate(1, 1); 
              c_polyData3.SetPoints(points3); 
              c_polyData3.SetLines(lines3); 
              
              
              vtk.vtkPolyDataMapper2D[] c_polyDataMapper = new vtk.vtkPolyDataMapper2D[3]; 
              c_polyDataMapper[0]=new vtk.vtkPolyDataMapper2D();
			  c_polyDataMapper[0].SetInput(c_polyData1); 
			  c_polyDataMapper[1]=new vtk.vtkPolyDataMapper2D();
			  c_polyDataMapper[1].SetInput(c_polyData2); 
			  c_polyDataMapper[2]=new vtk.vtkPolyDataMapper2D();
			  c_polyDataMapper[2].SetInput(c_polyData3); 
             
    		  for(int i=0; i<3;i++){
    			  
    			  
    			  EnduModel.legendActor[m][i] = new vtkActor2D(); 
                 // EnduModel.legendActor[m][i].GetProperty().SetOpacity(1); 
                  EnduModel.legendActor[m][i].GetProperty().SetLineWidth(20.0f); 
                  EnduModel.legendActor[m][i].SetMapper(c_polyDataMapper[i]); 
                  EnduModel.legendActor[m][i].VisibilityOn(); 
                  
              	  double saturation = (max-value[i])/(max-min);
              	  double[] rgb= getRGB(m, color, saturation); 
	    		  EnduModel.legendActor[m][i].GetProperty().SetColor(rgb[0],rgb[1],rgb[2]); 
                  EnduModel.ren.AddViewProp(EnduModel.legendActor[m][i]); 
    		  }   
	  }	


	public static void createLegendMissingValue() {
		//Add the actors to the renderer, set the background and size
			  
			  vtkTextActor textActor = new vtkTextActor();
			  textActor.SetDisplayPosition(0,8);
			  textActor.SetInput("MissingValue");
		      textActor.GetPosition2Coordinate().SetCoordinateSystemToNormalizedViewport();
			  textActor.GetPosition2Coordinate().SetValue(0.2, 0.1);

			  vtkTextProperty tprop = textActor.GetTextProperty();
			  tprop.SetFontSize(16);
			  tprop.SetFontFamilyToArial();
			  tprop.SetJustificationToLeft();
			  tprop.BoldOn();
			  tprop.ItalicOn();
			  tprop.ShadowOn();
			  tprop.SetColor(0, 0, 0);
			  EnduModel.ren.AddActor2D(textActor);

			 	  int id = 0; 
	              vtkPoints points1 = new vtkPoints(); 
	              points1.SetNumberOfPoints(2); 
	              while (id < 2)
	              { 
	                  if (id==0) {
	                	  points1.InsertPoint(id,106,13 , 0);             
	                  }
	                  else{
	                	  points1.InsertPoint(id,282,13 , 0);               
	                  }
	            	  id++; 
	              } 
	              vtk.vtkCellArray lines1 = new vtk.vtkCellArray(); 
	              lines1.Allocate(1, 1); 
	              lines1.InsertNextCell(id); 
	              lines1.SetNumberOfCells(id); 
	            
	              for (int k = 0; k < id; ++k) {
	            	  lines1.InsertCellPoint(k);
	            	  
	              }

	              vtkPolyData c_polyData1 = new vtkPolyData(); 
	              c_polyData1.ReleaseDataFlagOn(); 
	              c_polyData1.Allocate(1, 1); 
	              c_polyData1.SetPoints(points1); 
	              c_polyData1.SetLines(lines1); 
	              
	              vtk.vtkPolyDataMapper2D c_polyDataMapper =new vtk.vtkPolyDataMapper2D();
				  c_polyDataMapper.SetInput(c_polyData1); 
				 	  
				  vtkActor2D legendActor  = new vtkActor2D(); 
	                 // EnduModel.legendActor[m][i].GetProperty().SetOpacity(1); 
	                  legendActor.GetProperty().SetLineWidth(20.0f); 
	                  legendActor.SetMapper(c_polyDataMapper); 
	                  legendActor.VisibilityOn(); 
	                  
	              	  legendActor.GetProperty().SetColor(0,0,0); 
	                  EnduModel.ren.AddViewProp(legendActor); 
	 }	

	public static double[] getRGB(int measure, int color, double saturation) {
		double[] rgb= new double[3];
		saturation=saturation*0.75;
	if (color==0){
		rgb[0]= 1.;
		rgb[1]= saturation*EnduModel.colorRate;
		rgb[2]= saturation*EnduModel.colorRate;
	}
	if (color==1){
		rgb[0]= saturation*EnduModel.colorRate;
		rgb[1]= saturation*EnduModel.colorRate;
		rgb[2]= 1;
	}
	if (color==2){
		rgb[0]= saturation*EnduModel.colorRate;
		rgb[1]= (EnduModel.colorRate-0.6)*saturation+0.6;
		rgb[2]= (EnduModel.colorRate-0.6)*saturation+0.6;
	}
	if (color==3){
		rgb[0]= (saturation)*EnduModel.colorRate;
		rgb[1]= (saturation)*EnduModel.colorRate;
		rgb[2]= (saturation)*EnduModel.colorRate;
	}
	if (color==4){
		rgb[0]= 1.;
		rgb[1]= 1.;
		rgb[2]= saturation;
	}
	if (color==5){
		rgb[0]= (EnduModel.colorRate-34./255.)*saturation+34./255.;
		rgb[1]= (EnduModel.colorRate-112./255.)*saturation+112./255.;
		rgb[2]= (EnduModel.colorRate-128./255.)*saturation+128./255.;
	}
	if (color==6){
		rgb[0]= (EnduModel.colorRate-258./255.)*saturation+253./255.;
		rgb[1]= (EnduModel.colorRate-72./255.)*saturation+72./255.;
		rgb[2]= (EnduModel.colorRate-41./255.)*saturation+41./255.;
	}
	if (color==7){
		rgb[0]= (EnduModel.colorRate-49./255.)*saturation+49./255.;
		rgb[1]= (EnduModel.colorRate-0.5)*saturation+0.5;
		rgb[2]= (EnduModel.colorRate-43./255.)*saturation+43./255.;
	}
	if (color==8){
		rgb[0]= (EnduModel.colorRate-0.5)*saturation+0.5;
		rgb[1]= (EnduModel.colorRate-0.16)*saturation+0.16;
		rgb[2]= (EnduModel.colorRate-0.05)*saturation+0.05;
	}
	if (color==9){
		rgb[0]= saturation*(EnduModel.colorRate-0.5)+0.5;
		rgb[1]= saturation*(EnduModel.colorRate-0.5)+0.5;
		rgb[2]= saturation*(EnduModel.colorRate-0.5)+0.5;
	}
	if (color==10){
		rgb[0]= saturation*EnduModel.colorRate;
		rgb[1]= 1.;
		rgb[2]= saturation*EnduModel.colorRate;
	}
	return rgb;
 }

	public static String formatDouble(double d) {
	  int num  = (int) d;
	  int num2 = (int) ((d-num)*10);
	  num2 =Math.abs(num2);
	  String str = num +"." +num2;
	  return str;
	}

}
