#include <stdio.h>
#include <cmath>
#include <cstdlib>
#include <string.h>
#include <algorithm>
#include <sstream>

int main(int argc, char *argv[]){
	//Check arguments and output usage
    if(argc != 5){
        fprintf(stderr, "Usage: %s <input file 1> <input file 2> <output name> <max graphlet size>\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; }
    	}

	int maxGraphletSize = atoi(argv[4]);

	if (maxGraphletSize < 3 || maxGraphletSize > 5)
	{
		fprintf(stderr, "Incorrect max graphlet size (should be in {3,4,5}");
		return 1;
	}



	//Initialize the weights for each orbit (edge and non-edge)
	float weights[] = { 1, 0.838444533, 0.838444533, 0.838444533, 0.743940642, 0.676889065, 0.743940642, 0.743940642, 0.676889065, 0.743940642, 0.676889065, 0.676889065, 0.676889065, 0.676889065, 0.743940642, 0.676889065, 0.582385175, 0.624879821, 0.676889065, 0.624879821, 0.582385175, 0.582385175, 0.676889065, 0.676889065, 0.676889065, 0.624879821, 0.546456463, 0.676889065, 0.582385175, 0.582385175, 0.546456463, 0.676889065, 0.582385175, 0.582385175, 0.582385175, 0.624879821, 0.582385175, 0.546456463, 0.546456463, 0.624879821, 0.546456463, 0.582385175, 0.546456463, 0.582385175, 0.624879821, 0.624879821, 0.582385175, 0.515333598, 0.546456463, 0.582385175, 0.582385175, 0.515333598, 0.582385175, 0.487881285, 0.624879821, 0.582385175, 0.676889065, 0.582385175, 0.582385175, 0.546456463, 0.515333598, 0.582385175, 0.582385175, 0.515333598, 0.546456463, 0.582385175, 0.546456463, 0.546456463, 0.515333598, 0.624879821, 0.582385175, 0.582385175, 0.676889065};
	
	if (maxGraphletSize == 3)
	{
		for (int i = 4; i < 73; ++i)
			weights[i] = 0;
	}
	else if (maxGraphletSize == 4)
	{
		for (int i = 15; i < 73; ++i)
			weights[i] = 0;
	}


	int i;
	


	char line[1024];
	char line2[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, 1024, fp2);
	node1 = strtok( line, " ");
    value = strtok( NULL, " ");
	n = 0;
	while( value != NULL){
       if( n > 72 ){
           fprintf( stderr, "Error: invalid input file\n");
           return 1;
           }
       n++;
       value = strtok( NULL, " ");
       }
    n--;
    if( n != 72 ){
            fprintf( stderr, "Error: invalid input file\n");
            return 1;
            }
    
    //Find total weight
    float total_weight = 0;
	for( i = 0; i <= 72; i++){
        total_weight += weights[i];
        }
    
    //Print out node names for file 2
    //And find the number of lines
    fprintf( out, "  %s", node1);
    while( fgets( line, 1024, 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, 1024, fp1 ) != NULL ){
	    fseek ( fp2 , 0 , SEEK_SET );
	    char line_copy[1024];
	    strcpy( line_copy, line);
	    node1 = strtok( line_copy, " ");
	    fprintf( out,"%s", node1);
	    //Put a line of file 2 into an array
	    while( fgets( line2, 1024, fp2) ){
	        int values2[73];
	        n = 0;
	        strtok( line2, " ");
	        value = strtok( NULL, " ");
	        while( value != NULL){
	            if( n > 72 ){
                    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 > 72 ){
                    fprintf( stderr, "Error: invalid input file\n");
                    return 1;
                    }
                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;
}
