#include <iostream>
#include <fstream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<map>
#include<utility>
#include<sstream>
#include<algorithm>
#include<set>
#include<cmath>
#include<time.h>


using namespace std;


int main(int argc, char *argv[]){
	//Check arguments and output usage
    if(argc != 6){
        fprintf(stderr, "Usage: %s <input file 1> <input file 2> <output name> <weights file> <num of orbits>\n", argv[0]);
        return 1;
    	}

	//Open input files
    FILE *fp1 = fopen(argv[1], "r");
    if(!fp1) { perror(argv[1]); return 1; }

    FILE *fp2 = fopen(argv[2], "r");
    if(!fp2) { perror(argv[2]); return 1; }
    
    FILE *out;
	
	//If - use standard out
    if(!strcmp(argv[3], "-")){ out = stdout; }
    else{
    //Otherwise, open out file
        out = fopen(argv[3], "w");
        if(!out){ perror(argv[3]); return 1; }
    	}

   string weightF=argv[4];
   int weight_size=atoi(argv[5]);
   float weights[weight_size];
   //read the file containing weights
   ifstream ofile(weightF.c_str());
   int icounter=0;
   while (ofile){
	string s;
	if (!getline(ofile, s)) break;
	istringstream ss(s);
	int ic = 0;
	while (ss){
	  string s;
       	  if (!getline(ss, s, '\t')) break;
		if (ic == 2) {
			weights[icounter]=atof(s.c_str()); //initialize the weights for each orbit
			ic=0;
			icounter++;
		}else{
			ic++;
		}
	}
  }
   	
	int i;
	int line_size=15*weight_size;
	char line[line_size]; //line[1024];
	char line2[line_size];  //line[1024]
	char* value = NULL;
	char* node1 = NULL;
	int n = 1;
	int l = 0;
	int num_lines = 0;
	float num = 0;
	float sum = 0;
	
	//Check that the file has all node orbit columns
	fgets( line, line_size, fp2);
	node1 = strtok( line, " ");
        value = strtok( NULL, " ");
	n = 0;
	while( value != NULL){
           if( n > weight_size-1 ){//72
           fprintf( stderr, "Error: invalid input file\n");
           return 1;
           }
           n++;
           value = strtok( NULL, " ");
       }
       n--;
       if( n != weight_size-1 ){//72
            fprintf( stderr, "Error: invalid input file\n");
            return 1;
            }


    //Find total weight
    float total_weight = 0;
	for( i = 0; i < weight_size; i++){
        total_weight += weights[i];
//cout<<"iweight: "<<weights[i]<<endl;
        }
    
    //Print out node names for file 2
    //And find the number of lines
    fprintf( out, "  %s", node1);
    while( fgets( line, line_size, fp2 ) != NULL ){
	    node1 = strtok( line, " ");
	    fprintf( out, " %s", node1);
	    num_lines++;
    }
    fprintf( out, "\n");
	
    //Go back to beginning of file
    fseek ( fp2 , 0 , SEEK_SET );

    if(!fp2) { perror(argv[2]); return 1; }
    l = 0;
    
    
    //For each line, calculate the eGDS with every line in the other file
	while( fgets( line, line_size, fp1 ) != NULL ){
	    fseek ( fp2 , 0 , SEEK_SET );
	    char line_copy[line_size];
	    strcpy( line_copy, line);
	    node1 = strtok( line_copy, " ");
	    //cout<<"node in file 1: "<<node1<<endl;
	    fprintf( out,"%s", node1);
	    //Put a line of file 2 into an array
	    while( fgets( line2, line_size, fp2) ){
	        int values2[weight_size]; //73
	        n = 0;
	        strtok( line2, " ");
	        value = strtok( NULL, " ");
		//cout<<"value in fp2: "<<value<<endl;
	        while( value != NULL){

	            if( n > weight_size-1 ){
                    fprintf( stderr, "Error: invalid input file\n");
                    return 1;
                    }
                    values2[n] = atoi( value );
                    value = strtok( NULL, " ");
                    n++;
                }
                
	        n = 0;
	        sum = 0;
	        strcpy( line_copy, line);
	        node1 = strtok( line_copy, " ");
	        value = strtok( NULL, " ");
	        while( value != NULL){
                    if( n > weight_size-1 ){
                    fprintf( stderr, "Error: invalid input file\n");
                    return 1;
                    }
 		  // cout<<"before calculation."<<endl;
		  // cout<<"n="<<n<<" value2-"<<values2[n]<<" value-"<<value<<endl;
                   num = (log( values2[n] + 1)  - log(atoi( value ) + 1) );
                if( num < 0 ){ num = -num;}
                num *= weights[n];
                num /= log(std::max(values2[n], atoi(value) ) + 2);
                sum += num;
                n++;
                value = strtok( NULL, " ");
                }
            sum /= total_weight;
            fprintf( out, " %f", 1 - sum);
            }
        fprintf( out,"\n");
        }  

    fclose(fp1);
    fclose(fp2);
    if(out != stdout) fclose(out);
    return 0;
}
