#include <jni.h>
#include "bicat_run_machine_RunMachine_cHawk.h"
#include <iostream>
#include <fstream>
#include <cmath>
#include "SphierStruct.h"

using namespace std;

typedef pair<Node*, int> Neighbor;

JNIEXPORT void JNICALL Java_bicat_run_1machine_RunMachine_1cHawk_run_1cHawk
  (JNIEnv * env, jobject obj, jdoubleArray data, jint int1, jint int2, jint int3, 
  jdouble double1, jint iter, jdouble double2, 
  jdouble double3, jdouble double4, jint int4, jint int5, jint int6, jstring jname){
   
   const char* cs = env->GetStringUTFChars (jname, NULL);
   char *cstring = new char [strlen (cs) + 1]; // +1 for null terminator
   sprintf (cstring, "%s", cs);
   
   SphierStruct* sp = new SphierStruct((int)int1, (int)int2,
                       double1,2,2,cstring);
   //cerr<<"sp was created"<<endl;
   env->ReleaseStringUTFChars (jname, cs);
   cerr <<"rows ="<<int1<<" cols ="<<int2<<endl;
   ofstream myfile;
   myfile.open("outputmat.chawk");
      
   for(int i=0; i< int1; i++){
   	   char res[10];
       string name(sp->itoa(i,res,10));
   	   sp->addNode(name,0);
   	  //cerr<<"adding row "<<name<<endl;
   }
   for(int j=0;j< int2; j++){
   	  char res[10];
      string name(sp->itoa(j,res,10));
      sp->addNode(name,1);
  	  //cerr<<"adding col "<<name<<endl;
   }
   //cerr<<"after adding nodes"<<endl;
   jdouble* elts= 
   env->GetDoubleArrayElements(data, 0);
  
   int row_std_dev[int1];
   int col_std_dev[int2];
   int colmeans[(int)int2];
   //int colcount[int2];
   int colsum[int2];
   for(int i=0; i< int2; i++){
   	   colmeans[i]=0;
   	   //colcount[i]=0;
   	   colsum[i]=0;
   	   col_std_dev[i]=0;
   }
   int rowmeans[(int)int1];
   for(int i=0; i< int1; i++){
   	   rowmeans[i]=0;
   	   row_std_dev[i]=0;
   }
   int matrix[(int)int1][(int)int2];
   int row=0; int col =0;
   for(int i=0; i< (int) int1*int2; i++){
   	   matrix[row][col] = (int) (100*elts[i]);
   	   colsum[col] += matrix[row][col];
   	   //colcount[col] += 1;
   	   //cerr<<"colsum "<<col<<" = "<<colsum[col]<<endl;
   	   colmeans[col] = colsum[col]/(row+1);
   	   rowmeans[row] += matrix[row][col];
   	   //cerr<<"Rowsum "<<row<<" = "<<colsum[col]<<endl;
   	   col += 1;
   	   if( (i+1) % (int)int2 == 0){
		   	 //myfile<<endl;
		   	 rowmeans[row] = rowmeans[row]/int2;
  	    	 myfile<<"Rowmean "<<row<<" = "<<rowmeans[row]<<endl;
		   	 row += 1;
		   	 col = 0;
   	   }
   	
   }
   
  
   for(int i=0; i <int1; i++){
   		for(int j=0; j< int2; j++){
   			col_std_dev[j] += (int)pow ((double)(matrix[i][j]-colmeans[j]),2);
   			row_std_dev[i] += (int)pow((double)(matrix[i][j]-rowmeans[i]),2);
   		}
   		row_std_dev[i] = sqrt(row_std_dev[i])/int2;
   		myfile<<"row std dev "<<i<<" "<<row_std_dev[i]<<endl;
   }
   
   for(int n=0; n <int2; n++){
   	col_std_dev[n] = sqrt(col_std_dev[n])/int1;
   	myfile<<"colmean "<<n<<" "<<colmeans[n]<<endl;
   	myfile<<"col std dev "<<n<<" "<<col_std_dev[n]<<endl;
   }
   
   
   Node* rownode;
   for(int i=0; i <int1; i++){
	   	rownode = sp->findNode(i,0);
	   //	cerr<<"rownode = "<<rownode->name<<endl;;
	   	if(rowmeans[i] == 0) rowmeans[i]=1;
   		for(int j=0; j <int2; j++){
   			if(colmeans[j] == 0) colmeans[j]=1;
   			myfile<<"before norm mat i j"<<matrix[i][j]<<endl;
//   			matrix[i][j] = matrix[i][j]/(colmeans[j]);
//   			matrix[i][j] =matrix[i][j]/rowmeans[i];
            if(matrix[i][j] > (rowmeans[i]+int6*row_std_dev[i])
               && matrix[i][j] > (colmeans[j]+int6*col_std_dev[j]))
               		matrix[i][j] = 1;
               	else
               		matrix[i][j] = 0;
               	
   			myfile<<"after norm mat i j"<<matrix[i][j]<<endl;   			
//   			if(matrix[i][j] > rowmeans[i] && matrix[i][j] > colmeans[j])
//   				matrix[i][j] = 1;
//   			else
//   				matrix[i][j]=0;
   			//if(matrix[i][j] == 0) continue;
   			Node* neb = sp->findNode(j,1);
 		 //   cerr<<"found col "<<neb->name<<endl;
 		  //  cerr<<"mat "<<i<<" "<<j<<" "<<matrix[i][j]<<endl;
 		    myfile<<matrix[i][j]<<" ";
   		 	Neighbor nebor(neb,matrix[i][j]);
 	  	 	//Neighbor nebor(neb,(int)(elts[i]));
	   	 	Neighbor n2(rownode,matrix[i][j]);
	   	 	//Neighbor n2(rownode,(int)(elts[i]));
   		 	rownode->addNeighbor(nebor);
  	 	 	//cerr<<"nebor added"<<endl;
  	 	 	neb->addNeighbor(n2);
  	 		
   		}
   		myfile<<endl;
   }
//   for(int i=0; i< (int) int1*int2; i++){
//   	 //if(elts[i] != 0){
//   	 	//jdoubleArray oneDim= 
//	 	//     (jdoubleArray)env->GetObjectArrayElement((jobjectArray)data,i);
//	 	//myfile<<oneDim<<endl;
//     	//jdouble *element=env->GetDoubleArrayElements(oneDim, 0);
//   	 	//for(int j=0; j< (int) int2; j++){
//   	 	//cerr<<(int)(100*elts[i])<<endl;
//   	 	if(col == 0){
//	   	 	rownode = sp->findNode(row,0);
//   	 	    //rownode = new Node();	
//   	 	   //cerr<<"found row "<<rownode->name<<endl;
//   	 	} 
//   	 	Node* neb = sp->findNode(col,1);
// 	    //cerr<<"found col "<<neb->name<<endl;
//   	 	Neighbor nebor(neb,(int)(100*elts[i]));
//   	 	//Neighbor nebor(neb,(int)(elts[i]));
//   	 	Neighbor n2(rownode,(int)(100*elts[i]));
//   	 	//Neighbor n2(rownode,(int)(elts[i]));
//   	 	rownode->addNeighbor(nebor);
//   	 	//cerr<<"nebor added"<<endl;
//   	 	neb->addNeighbor(n2);
//   	 	col += 1;
//   	   if( (i+1) % (int)int2 == 0){
//		   	 //myfile<<endl;
//		   	 row += 1;
//		   	 col = 0;
//   	   }
//    }
   //}
   //cerr<<"after adding weights"<<endl;
   for(int it=1; it <=(int)iter; it++){
   		sp->setPositionBary(sp->invertStaticLayer());
   }
   //sp->printStruct();
   //cerr<<"after crossing minimization"<<endl;
   if(int3 == 6)
   		sp->printMatrix();
   else
   		sp->findBiclusters((int)int3);
   //cerr<<"after finding bixes"<<endl;
   jint len1 = env->GetArrayLength (data);
   //jdoubleArray i2d_0 = (jdoubleArray) env->GetDoubleArrayElements(data, 0);
  // Get the length of the extracted 1D array
   //jint len2 = jenv->GetArrayLength (i2d_0);	
   //jint len2 = env->GetArrayLength(i2d_0);
   
   //myfile<<len1<<" "<<len2<<endl;
}
