#include<map>
#include<stdio.h>
#include "config.h"
#include<iostream>
#define writef "writef"

using namespace std;

#define dis_file "distribution"

char axis[maxstr];
char exptname[maxstr];
char aver[maxstr];
int cal_ave;  //yes or no


//tokenize the line
int chop(char s[],char a[][maxstr],char delim[]){
    int n=0;
    char *str;
    
    str=(char*)strtok(s,delim);
    while(str!=NULL){
        strcpy(a[n],str);
        str=(char*)strtok(NULL,delim);
        n++;
    }
    
    return n;
}

// check if parameters set satisfy the constraints
int check(char param[][maxstr],char cond[][maxstr],int m,int n,char *red,char *xx){
    
    int i,j;
    
    int dd[maxstr];
    
    for (j=0;j<n;j++) dd[j]=1;
    
    for (i=0;i<m;i+=2){
        int ok=0;
        for (j=0;j<n;j+=2)
            if (strcmp(param[i],cond[j])==0&&strcmp(param[i+1],cond[j+1])==0){
                ok=1;dd[j+1]=0;
            }
        if (!ok) return 0;
    }

    red[0]=0;
    
    for (j=1;j<n;j+=2)
        if (dd[j]&&strcmp(cond[j-1],axis)!=0){
            strcat(red,",");
            strcat(red,cond[j-1]);
            strcat(red,"=");
            strcat(red,cond[j]);
        }else if (strcmp(cond[j-1],axis)==0) strcpy(xx,cond[j]);
    return 1;
}

    char a[maxtab][maxtab][50]; // store the table
    
    char b[maxstr][maxstr];  // set of parameters
    int column=0,row=0;
    
    
/*struct strCmp {
    bool operator()( const char* s1, const char* s2 ) const {
      return strcmp( s1, s2 ) < 0;
    }
  };*/
    
void concate(char *s1,char *s2,char *s3){
    int i;
    
    int n=strlen(s1);
    for (i=0;i<strlen(s2);i++) s1[n++]=s2[i];
    for (i=0;i<strlen(s3);i++) s1[n++]=s3[i];
    s1[n]=0;
}

//  map<const char*, int, strCmp> map_row;
//  map<const char*, int, strCmp> map_col;
  
    double re[maxstr][maxstr];
    
int search(char a[][50],int col,char s[]){
    int i;
    for (i=1;i<col;i++)
        if (strcmp(a[i],s)==0) return i;
    return -1;
}

void add(char *s,char *value){
    double x,y;
    
    sscanf(s,"%lf",&x);
    sscanf(value,"%lf",&y);
    x=x+y;
    sprintf(s,"%lf",x);
}

int ddd[maxstr];
int limit;

// distribute the class equally
int readResults2(char name[],int argc,char argv[][maxstr]){
    int i=0,j;
    column=1;

    char header[maxstr];
    row=0;
    int ccc[maxstr];
    ccc[0]=1;
    strcpy(a[0][0],"a");

    while(1){
        FILE *f;

        char number[maxstr];
        sprintf(number,"%i",i);

        char file[maxstr];

        strcpy(file,tempdir);
        strncat(file,name,maxstr);

        concate(file,".",number);

        f=fopen(file,"r");
        
        if (f==NULL) break;

        char value[maxstr],ss[maxstr];
        char ss1[maxstr],ss2[maxstr],ss3[maxstr],ss4[maxstr],ss5[maxstr],ss6[maxstr];
        char line[maxstr];

/*        while(fgets(line,maxstr,f)){
             char *s=strtok(line," ");
             
             if (strcmp(s,"Time")!=0) break;
        }
        
        sscanf(line,"%s %s %s %s %s %s\n",ss4,ss,ss1,ss2,ss3,value);*/

        fscanf(f,"%s %s %s %s %s %s %s\n",value,ss4,ss,ss1,ss2,ss3,ss5);
        fscanf(f,"%s\n",ss6);
//        fscanf(f,"%s\n",ss);
//        fscanf(f,"%s %s\n",ss,ss2);
        rem(value);

        int n=0;

        while(fgets(line,maxstr,f)){
                rem(line);
                char *s=(char*)strtok(line,":* ");
                strcpy(b[n],s);
                n++;
                
                s=(char*)strtok(NULL,":* ");
                strcpy(b[n],s);
                n++;

                if (strcmp(b[n-2],aver)==0) strcpy(b[n-1],"1");    ///
        }

        char xx[maxstr];

        if (check(argv,b,argc,n,header,xx)){
            int x=search(a[0],column,header);

            if (x==-1){
                strcpy(a[0][column],header);
                strcpy(a[1][column],value);

                ccc[column]=2;

                x=column;
                column++;

            }else{
                strcpy(a[ccc[x]][x],value);
                
                ccc[x]++;
            }
            
            strcpy(a[ccc[x]-1][0],xx);

            if (ccc[x]>row) row=ccc[x];
        }
        i++;
        if (i==160) break;
        fclose(f);

    }        

    if (i==0) return 0;
   
    for (i=0;i<row;i++) ddd[i]=1;

    if (strcmp(axis,"run")==0){
        double sta,end,step=10;
        FILE *f;
        f=fopen(dis_file,"r");
                
        double x;        
        sscanf(a[1][1],"%lf",&x);
        sta=x;
        end=x;

        for (i=1;i<row;i++)
            for (j=1;j<column;j++){
                sscanf(a[i][j],"%lf",&x);
                if (x<sta) sta=x;
                if (x>end) end=x;                
            }

        if (f!=NULL){
            char s[maxstr];
            while(fscanf(f,"%s",s)!=EOF){
                if (strcmp(s,"-s")==0){
                    fscanf(f,"%lf",&sta);
                }else if (strcmp(s,"-e")==0){
                    fscanf(f,"%lf",&end);
                }else if (strcmp(s,"-sp")==0){
                    fscanf(f,"%lf",&step);
                }
            }
            fclose(f);
        }

        double bin=(end-sta)/step;

        for (i=0;i<step+1;i++)
            for (j=0;j<column;j++) re[i][j]=0;

        for (i=1;i<row;i++)
            for (j=1;j<column;j++){
                double x;
                sscanf(a[i][j],"%lf",&x);
                
                re[(int)((x-sta)/bin)][j]++;
            }
            
        for (i=0;i<step+1;i++){
            for (j=1;j<column;j++) sprintf(a[i+1][j],"%lf",re[i][j]);
            sprintf(a[i+1][0],"%lf",sta+i*bin);
        }

        row=(int)step+2;        
    }else{
        int l;
        for (i=1;i<row;i++)
            if (ddd[i]){
                int cnt=1;

                for (j=i+1;j<row;j++)
                    if (strcmp(a[i][0],a[j][0])==0){
                        ddd[j]=0;
                        cnt++;
                        
                        for (l=1;l<column;l++) add(a[i][l],a[j][l]);
                    }

                double x;
                for (l=1;l<column;l++){
                    sscanf(a[i][l],"%lf",&x);
                    sprintf(a[i][l],"%lf",x/cnt);
                }
            }        
    }
    
    return 1;
}

// draw the graph based on data in input
void draw(char *input,char *output){
    int i;
    FILE *f;
    f=fopen(input,"r");
    FILE *out;
    out=fopen(output,"w");
    FILE *da;
    
    char tempfile[maxstr];
    sprintf(tempfile,"%s%s.tmp",graphdir,input);
    
    da=fopen(tempfile,"w");

    char line[maxstr];

    char a[maxparam][maxstr];
    fgets(line,maxstr,f);
    rem(line);
    int nparam=chop(line,a,"|");

    fprintf(out,"set terminal png transparent nocrop enhanced font arial 8 size 420,320\n");

    fprintf(out,"set output '%s.png'\n",input);
    fprintf(out,"set style data linespoints\n");

    fprintf(out,"plot ");

    for (i=1;i<nparam-1;i++) fprintf(out,"'%s.tmp' using 1:%i title '%s',",input,i+1,a[i]);
    fprintf(out,"'%s.tmp' using 1:%i title '%s'",input,nparam,a[i]);

    while(fgets(line,maxstr,f)){
        rem(line);
        int n=chop(line,a,"|");

        for (i=0;i<n;i++) fprintf(da,"%s ",a[i]);
        fprintf(da,"\n");
    }

    fclose(f);
    fclose(out);
    fclose(da);
}

int realnum(char *s){
    int i;
    for (i=0;i<strlen(s);i++)
        if (s[i]!='.'&&(s[i]<'0'||s[i]>'9')) return 0;
    return 1;
}

void output(char fname[]){
    int i,j;

    cout<<row<<" "<<column<<endl;    
    FILE *f;
    
    f=fopen(fname,"w");


    int rr=1;
    for (i=0;i<row;i++)
        if (ddd[i]){
            double x;
            
            if (!realnum(a[i][0])){
                fprintf(f,"%i|",rr);
                rr++;
            }else fprintf(f,"%s|",a[i][0]);
            
            for (j=1;j<column;j++) fprintf(f,"%s|",a[i][j]);
            fprintf(f,"\n");
        }

    fclose(f);

    char comm[maxstr];
    sprintf(comm,"%s%s.plot",graphdir,fname);

    draw(fname,comm);
    
    sprintf(comm,"gnuplot %s",comm);
    system(comm);

//    printf("row :%i column: %i\n",row,column);    
    printf("Analyzing is completed\n");
    printf("The results are in %s\n",fname);
    printf("Graph is in %s.png\n",fname);
}

char arg[maxstr][maxstr];
int main(int argc,char *argv[]){
    
    if (argc<4||argc%2==1){
        printf("Parameters are incorrect\n");return 0;
    }
    
    int i;

    strcpy(axis,argv[3]);
    for (i=0;i<argc;i++) strcpy(arg[i],argv[i]);

    //read database
    if (readDatabase(argv[2])==0){
        printf("Name or id is not found\n");
        return 0;
    }
    
    
    if (num==-1){
        printf("Experiment not found\n");return 0;
    }

    int start=4;
    if (strcmp("-a",argv[4])==0){
        strcpy(aver,argv[5]);
        cal_ave=1;
        start=6;
    }else cal_ave=0;
    
    strcpy(exptname,arg[1]);
    
    //read results, summarize        
    readParam(param);
    
    if (readResults2(name,argc-start,arg+start)==0) cout<<"Experiment has not been run yet"<<endl;
    else output(exptname);    
}
