#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "software.h"  
#include "util.h"
#include "harv.h"
#include "CifFileObj.h"
#include "version.h"

void get_version_date(char *infile, char *prog, char *version, char *time);
void get_software_info_fixed(void);
void version_date_class(SOFTWARE_INF *software_info, char *prog,
                        char *infile, int nprog,const  char *clas);
void get_tmp(char *file);

SOFTWARE_INF software_info[40];

void get_software_info(FILE *fout, int argc, char **argv)
/* This routine is used to collect the software information,
   citation, and citation_authers  categories
*/
// cns = 0 
// mlphare=1
// solve=2
// sharp=3
// shelx=4
// SnB=5
// BnP=6
// dm=7
// resolve=8
// Solomon = 9
// REFMAC5=10
// tnt=11
// Warp=12
// restrain=13
// amore=14
// epmr=15
// MOLREP=16
// HKL/HKL200/SCALEPACK=17
// SCALA=18 
// DTREK=19
// PHASES=20
// SAINT=21
// 3DSCALE=22
// pdb_extract=23
// SCALEPACK=24
// DEZON=25
// PHASER=26
    
{
 
    int i, nprog=0;
    
    
//    get_software_info_fixed() ;
    
    for(i=1; i<argc-1; i++){
        if(!strcmp_case(argv[i], "-r")){
            if(!strcmp_case(argv[i+1], "CNS")){
                software_info[nprog]=software_all[0];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");

                nprog++;
            }else if(strstr_case(argv[i+1], "REFMAC") ){
                
                software_info[nprog]=software_all[10];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "TNT") ){
                software_info[nprog]=software_all[11];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "WARP") ){
                software_info[nprog]=software_all[12];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "SHELXL") ){
                software_info[nprog]=software_all[4];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "RESTRAIN") ){
                software_info[nprog]=software_all[13];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "refinement");
                nprog++;
            }
            
        }else if(!strcmp_case(argv[i], "-p")){
            if(!strcmp_case(argv[i+1], "cns")){
                software_info[nprog]=software_all[0];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "mlphare")){
                software_info[nprog]=software_all[1];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if (!strcmp_case(argv[i+1], "solve")){
                software_info[nprog]=software_all[2];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if (!strcmp_case(argv[i+1], "sharp")){
                software_info[nprog]=software_all[3];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if (strstr_case(argv[i+1], "shelx")){
                software_info[nprog]=software_all[4];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if (!strcmp_case(argv[i+1], "SnB")){
                software_info[nprog]=software_all[5];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }else if (!strcmp_case(argv[i+1], "BnP")){
                software_info[nprog]=software_all[6];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
                
            }else if (!strcmp_case(argv[i+1], "phases")){
                software_info[nprog]=software_all[20];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "phasing");
                nprog++;
            }
            
        }else if(!strcmp_case(argv[i], "-d")){
            if(!strcmp_case(argv[i+1], "cns")){
                software_info[nprog]=software_all[0];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "dm")){
                software_info[nprog]=software_all[7];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "resolve")){
                software_info[nprog]=software_all[8];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
            }else if(strstr_case(argv[i+1], "shelx")){
                software_info[nprog]=software_all[4];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "SOLOMON")){
                software_info[nprog]=software_all[9];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
            }else if(!strcmp_case(argv[i+1], "SHARP")){
                software_info[nprog]=software_all[3];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "density modification");
                nprog++;
                
            }
        }else if(!strcmp_case(argv[i], "-m")){
            if(!strcmp_case(argv[i+1], "CNS")){
                software_info[nprog]=software_all[0];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "molecular replacement");   
                nprog++;
            }else if(!strcmp_case(argv[i+1], "amore")){
                software_info[nprog]=software_all[14];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "molecular replacement");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "epmr")){
                software_info[nprog]=software_all[15];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "molecular replacement");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "MOLREP")){
                software_info[nprog]=software_all[16];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "molecular replacement");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "PHASER")){
                software_info[nprog]=software_all[26];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "molecular replacement");                
                nprog++;
            }       
        }else if(!strcmp_case(argv[i], "-s")){
            if(strstr_case(argv[i+1], "HKL") ){
                software_info[nprog]=software_all[17];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data  processing");   
                nprog++;
            }else if(!strcmp_case(argv[i+1], "scalepack" )){
                software_info[nprog]=software_all[24];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data scaling");   
                nprog++;
            }else if(!strcmp_case(argv[i+1], "scala")){
                software_info[nprog]=software_all[18];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data processing");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "dtrek")){
                software_info[nprog]=software_all[19];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data processing");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "saint")){
                software_info[nprog]=software_all[21];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data processing");                
                nprog++;
            }else if(!strcmp_case(argv[i+1], "3dscale")){
                software_info[nprog]=software_all[22];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "data processing");                
                nprog++;
            }       
        }else if(!strcmp_case(argv[i], "-i")){
             if(!strcmp_case(argv[i+1], "denzo" )){
                software_info[nprog]=software_all[25];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "collction/data indexing");   
                nprog++;
             }else if(!strcmp_case(argv[i+1], "dtrek" )){
                software_info[nprog]=software_all[19];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "collction/data indexing");   
                nprog++;
                 
             }else if(!strcmp_case(argv[i+1], "mosflm" )){
                software_info[nprog]=software_all[27];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "collction/data indexing");   
                nprog++;
                 
             }else if(!strcmp_case(argv[i+1], "saint" )){
                software_info[nprog]=software_all[21];
                version_date_class(software_info, argv[i+1], argv[i+3], nprog,
                                   "collction/data indexing");   
                nprog++;
             }
             
        }
        
        
    }
    
    if(nprog<=0) return;
    
    software_info[nprog]=software_all[23]; //for pdb_extract
    version_date_class(software_info, (char *) "pdb_extract", (char *)"?", nprog,"data extraction");
    
    nprog++;
    
    fprintf(fout, "loop_\n");
    fprintf(fout, "_software.name      \n");
    fprintf(fout, "_software.version   \n");
    fprintf(fout, "_software.date      \n");
    fprintf(fout, "_software.type       \n");
    fprintf(fout, "_software.contact_author       \n");
    fprintf(fout, "_software.contact_author_email \n");
    fprintf(fout, "_software.classification       \n");
    fprintf(fout, "_software.location    \n");
    fprintf(fout, "_software.language    \n");
    fprintf(fout, "_software.citation_id \n\n");    
    for(i=0; i<nprog; i++){
        fprintf(fout,"'%s'\n", software_info[i].software.name);
        fprintf(fout,"'%s'\n", software_info[i].software.version);
        fprintf(fout,"'%s'\n", software_info[i].software.date);
        fprintf(fout,"'%s'\n", software_info[i].software.type);
        fprintf(fout,"'%s'\n", software_info[i].software.contact_author);
        fprintf(fout,"'%s'\n", software_info[i].software.contact_author_email);
        fprintf(fout,"'%s'\n", software_info[i].software.classification);
        fprintf(fout,"'%s'\n", software_info[i].software.location);
        fprintf(fout,"'%s'\n", software_info[i].software.language);
        fprintf(fout,"%d\n\n", software_info[i].software.citation_id);   
    }
    
    fprintf(fout,"###\n\n");
/*  disable this currently, since the citation in mmCIF is not related
    fprintf(fout, "loop_\n");
    fprintf(fout, "_citation.id\n");
    fprintf(fout, "_citation.title\n");
    fprintf(fout, "_citation.journal_abbrev\n");
    fprintf(fout, "_citation.journal_volume\n");
    fprintf(fout, "_citation.page_first\n");
    fprintf(fout, "_citation.page_last\n");
    fprintf(fout, "_citation.year\n");
    fprintf(fout, "_citation.details\n");
    for(i=0; i<nprog; i++){
        fprintf(fout,"%d\n",i+1);
        fprintf(fout,"'%s'\n",software_info[i].citation.title);
        fprintf(fout,"'%s'\n",software_info[i].citation.journal_abbrev);
        fprintf(fout,"'%s'\n",software_info[i].citation.journal_volume);
        fprintf(fout,"'%s'\n",software_info[i].citation.page_first);
        fprintf(fout,"'%s'\n",software_info[i].citation.page_last);
        fprintf(fout,"'%s'\n",software_info[i].citation.year);
        fprintf(fout,"'%s'\n\n",software_info[i].citation.details);
    }
    fprintf(fout,"###\n\n");

    
    fprintf(fout, "loop_\n");
    fprintf(fout, "_citation_author.citation_id\n");
    fprintf(fout, "_citation_author.ordinal\n");
    fprintf(fout, "_citation_author.name\n");
    for(i=0; i<nprog; i++){
        for(j=0; j<software_info[i].citation_author[0].ncite; j++){
            fprintf(fout," %d %d '%s'\n",i+1, j+1,
                    software_info[i].citation_author[j].name);
        }
    }
*/

}


void version_date_class(SOFTWARE_INF *software_info, char *prog,
                        char *infile, int nprog,const char *clas)
{
    char version[80], date[80];

    if(!strcmp_case(prog, "pdb_extract")){
        strcpy(version, PDB_EXTRACT_VERSION);
        strcpy(date,PDB_EXTRACT_DATE );
    }else{
        get_version_date(infile, prog, version, date);
        rid_of_front_end_space(version);
        rid_of_front_end_space(date);
    }
    if(strlen(version)<=0) strcpy(version , "?");
    if(strlen(date)<=0) strcpy(date , "?");
   
//    printf("!version, date %s, %s, %s\n", version, date, clas);
    strcpy(software_info[nprog].software.version, version);
    strcpy(software_info[nprog].software.date , date);
    strcpy(software_info[nprog].software.classification , clas);
    software_info[nprog].software.citation_id  = nprog+1;
    
}


void get_version_date(char *infile, char *prog, char *version, char *date)
 /* some of the version and date can be extracted from the log file*/
{
    char str[256],  *ptr=NULL;
    int n=0, m=0;
    FILE *fp;
    
    strcpy(version,"?");
    strcpy(date,"?");
    
    if((fp = fopen(infile, "r")) ==NULL) {
        return;  //do not exit!
    }

    if(!strcmp_case(prog, "cns")){
        m=0;
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>200) break;
            
            rid_of_front_space(str);
            if(!strncmp_case(str, "_software.version", 17)){
                get_string(str, 17, 50, version);
            }else if (!strncmp_case(str, "_software.date", 14)){
                get_string(str, 17, 50, date);
                break;
            }else if(!strncmp(str, "REMARK   3   PROGRAM     : CNS", 30)){
                get_string(str, 30, 40, version);
                break;
                
            }   
        }
        
    }else if(!strcmp_case(prog, "mlphare") || !strcmp_case(prog, "scala")||
             strstr_case(prog, "refmac") || !strcmp_case(prog, "restrain")||
             !strcmp_case(prog, "truncate")){
        m=0;
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>200) break;
            
            rid_of_front_end_space(str);
            char2space(str, '\'');
            char2space(str, '"');
            char2space(str, '\n');
            if(!strncmp_case(str, "_software.version", 17)){
                
                n = sscanf(str+17, "%s", version);
                if(n!=1) break;
                strcpy(date,  strstr(str+17, version) + strlen(version));
               
                if(strlen(date)<=3)
                    strcpy(date, "?");
                
                break;
            }else if(!strncmp(str, "REMARK   3   PROGRAM     : REFMAC", 33)){
                get_string(str, 33, 50, version);
                break;
            }
            
                
        }
    
    }else if(strstr_case(prog, "solve") ||strstr_case(prog, "resolve") ){
        m=0;
       
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>50) break;
            
            if(pattern5(str, "(", "version","of", ")", "")){
                char2space(str, ')');
                ptr = strstr_case(str,"version")+7;
                n=sscanf(ptr, "%s%*s%s", version,date);
                if(n!=2) {
                   strcpy( version, "?");
                   strcpy( date, "?");
                }
                break;  
            }
        }
    }else if(!strcmp_case(prog, "epmr")){
        m=0;
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>10) break;
            rid_of_front_space(str);
            if(!strncmp(str,"EPMR", 4) &&
               pattern5(str, "EPMR", "version", "(", ")", "")){
                get_data_set_id(str,"version", "(",version);
                get_data_set_id(str,"(", ")",date);
                break;  
            }
        }
        
    }else if(!strcmp_case(prog, "molrep") || !strcmp_case(prog, "dm") ||
             !strcmp_case(prog, "amore")){
        m=0;        
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>50) break;
            if(pattern5(str, "##", "dm ", "version", ":", "##")){
                get_data_set_id(str,"version", ":",version);
                break;
            }else if(pattern5(str, "##", "CCP4", ": ","MOLREP(ccp4)",  " ####")){
                get_data_set_id(str,"(ccp4)", " #",version);
                break;
                
            }else if(pattern5(str, "##", "CCP4", ":","amore",  "####")){
                get_data_set_id(str,"# ", ":",version);
                break;
            }
            
        }
    }else if(!strcmp_case(prog, "dtrek")){
        m=0;        
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>50) break;
            if(pattern5(str, "d*TREK version", "--", "", "", "")){
                get_data_set_id(str,"version", "--" ,version);
                get_data_set_id(str, "--" , "\n", date);
                break;  
            }
        }
    }else if(!strcmp_case(prog, "saint")){
        m=0;        
        while (fgets(str, sizeof str, fp) != NULL){
            if(m++>2) break;
            rid_of_front_space(str);
            if(!strncmp_case(str, "SAINT ", 6)){
                get_data_set_id(str, "SAINT" , "\n", version);
                break;  
            }
        }
        
    }
    
    fclose(fp);
}

void    get_tmp(char *file)
        // it is only used for writing to struct. (not used here)
{
    FILE *finp;
    char str[500], *space4= (char *)"    ", *space8= (char *)"        ", *space12= (char *)"            ";
    int i=0, n=0;
    
    
    
    SOFTWARE software;
    CITATION citation;
    CITATION_AUTHOR citation_author[20];

    finp=fopen(file, "r");
    while((fgets(str, sizeof str, finp))!=NULL){
        if(strstr_case(str,".software.name")){
             strcpy(software.name , get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.version")){
            strcpy(software.version , get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.date")){
             strcpy(software.date, get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.type")){
             strcpy(software.type, get_substr(str,",", ")"));
            
        }else if (strstr_case(str,"software.contact_author") &&
                  !strstr_case(str,"software.contact_author_email")){
             strcpy(software.contact_author, get_substr(str,",", ")"));
            
        }else if (strstr_case(str,"software.contact_author_email")){
             strcpy(software.contact_author_email, get_substr(str,",", ")"));
            
        }else if (strstr_case(str,"software.location")){
            strcpy(software.location, get_substr(str,",", ")"));
            
        }else if (strstr_case(str,"software.classification")){
             strcpy(software.classification, get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.language")){
            strcpy(software.language , get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.description")){
            strcpy( software.description, get_substr(str,",", ")"));
        }else if (strstr_case(str,"software.citation_id")){
           software.citation_id = get_int(str,"=", ";");

           
        }else if (strstr_case(str,"citation.id")){
            citation.id= get_int(str,"=", ";");
        }else if (strstr_case(str,"citation.title")){
           citation.title = get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.journal_abbrev")){
            citation.journal_abbrev= get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.journal_volume")){
            citation.journal_volume= get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.page_first")){
           citation.page_first = get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.page_last")){
            citation.page_last= get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.year")){
            citation.year= get_substr(str,",", ")");
        }else if (strstr_case(str,"citation.details")){
           citation.details = get_substr(str,",", ")");

           
        }else if (strstr_case(str,"citation_author") &&
                  strstr_case(str,".citation_id")){
           citation_author[0].citation_id = get_int(str,"=", ";");
        }else if (strstr_case(str,"citation_author") &&
                  strstr_case(str,".ncite")){
           citation_author[0].ordinal = 1;
           
        }else if (strstr_case(str,"citation_author") &&
                  strstr_case(str,".name")){
            citation_author[n++].name= get_substr(str,",", ")");
        }else if( strstr(str,"//") && strlen(str)<20){
            
            printf("%s{\n",space4);
            printf("%s{\n",space8);
            printf("%s%d, %s, %s, %s, %s,\n",space12,
                   software.citation_id, software.name,
                   software.version, software.date, software.type);
            printf("%s%s, %s,\n",space12,
                   software.contact_author, software.contact_author_email);
            printf("%s%s,\n",space12,software.location);
            printf("%s%s, %s,\n",space12,
                   software.classification, software.language);
            printf("%s%s\n",space12, software.description);
            printf("%s},\n",space8);

            printf("%s{\n",space8);
            
            printf("%s%d, %s,\n",space12, citation.id, citation.title );
            printf("%s%s, %s, %s, %s,\n",space12,
                  citation.year, citation.journal_volume,
                   citation.page_first, citation.page_last);
            printf("%s%s,\n",space12,citation.journal_abbrev);
            printf("%s%s\n",space12,citation.details);
            printf("%s}, %d,\n",space8, n);
            

            printf("%s{\n",space8);

            for(i=0; i<n-1; i++){
                printf("%s{1, 1, %d, %s},\n",space12,n, citation_author[i].name);
            }
            printf("%s{1, 1, %d, %s}\n",space12,n, citation_author[n-1].name);
            n=0;
            printf("%s}\n",space8);
            printf("%s},\n\n",space4);
            
            printf("%s",str);
            
        }
    }
}

