#include "runsim.h"

int assign_rxn_index(char *rxtype)
{
               int i=0;
               if (!strcmp("binding", rxtype))
                       i = BINDING;
               else if (!strcmp("unique-bi-bi", rxtype))
                       i = UNIQUE_BI_BI;
               else if (!strcmp("unbinding", rxtype))
                       i = UNBINDING;
               else if (!strcmp("uni-uni", rxtype))
                       i = UNI_UNI;
               else if (!strcmp("uni-multi", rxtype))
                       i = UNI_MULTI;
               else if (!strcmp("homo-ltor", rxtype))
                       i = HOMO_LTOR;
               else if (!strcmp("transv1", rxtype))
                       i = TRANSV1;
               else if (!strcmp("genmm", rxtype))
                       i = GENM;
               else if (!strcmp("n-order", rxtype))
                       i = NTH_ORDER;
               else if (!strcmp("undef", rxtype))
                       i = UNDEFINED;
	return i;
}

void read_constants(struct rxn *rxn_ptr, struct array_sizes *arsz_ptr, struct cmpd_data *cmpds, struct run_constants *r_c, struct set_data *sets, char *constants_file)
{
	int i,  k, index;
	char junk[80];
	FILE *infile = fopen(constants_file, "r");
	if (infile == NULL)
    {
        printf("Can't open file %s. Exit!\n",constants_file);
        return;
    }
   
    for (i=0; i<8; i++)
	     fgets(junk, 80,infile);

//  Read compounds: name and initial number

		for (i = 0; i < arsz_ptr->num_cmpds; i++)
	                fscanf(infile,"%s %d", cmpds[i].name, &cmpds[i].value);
  
                fscanf(infile,"\n");

//  Read reactions                             

 	for (i = 0; i < arsz_ptr->num_rxns; i++) {
                fgets(junk, 80,infile);   // reaction name
		fscanf(infile, "rxntype = %s\n", rxn_ptr[i].type); // reaction type
		rxn_ptr[i].rxn_index = assign_rxn_index(rxn_ptr[i].type);
		fscanf(infile, "num_subs = %d", &arsz_ptr->num_subs[i]); // number of substrates

                rxn_ptr[i].substrates = (int *)calloc(arsz_ptr->num_subs[i], sizeof(int));
                rxn_ptr[i].numsubs_used = (int *)calloc(arsz_ptr->num_subs[i], sizeof(int));
                rxn_ptr[i].misc_subval = (double *)calloc(arsz_ptr->num_subs[i], sizeof(double));
 
		switch (rxn_ptr[i].rxn_index) 
        {
			case BINDING:
			case UNIQUE_BI_BI:
			case UNBINDING:
			case UNI_UNI:
			case UNI_MULTI:
			case HOMO_LTOR:
			{
    			for (index = 0; index < arsz_ptr->num_subs[i]; index++) 
					fscanf(infile, "%d\n", &(rxn_ptr[i].substrates[index]));
 	   	  		
				break;
			}

			case TRANSV1:
			case GENM:
            case UNDEFINED:
			{
    		   for (index = 0; index < arsz_ptr->num_subs[i]; index++) 
					fscanf(infile, " %d %d\n", &rxn_ptr[i].substrates[index], &rxn_ptr[i].numsubs_used[index]);
 	   	  		   
				break;
			}

			case NTH_ORDER:
			{
    			for (index = 0; index < arsz_ptr->num_subs[i]; index++) 
					fscanf(infile, " %d %d %le\n", &rxn_ptr[i].substrates[index], &rxn_ptr[i].numsubs_used[index], &rxn_ptr[i].misc_subval[index]);
 	   	  		
				break;
			}
                                         default:
                 printf("a specified reaction type is not defined \n");

               }


  		fscanf(infile, "num_prods = %d\n", &arsz_ptr->num_prods[i]); // number of products

		if (arsz_ptr->num_prods[i] != 0) 
        {
                rxn_ptr[i].products = (int *)calloc(arsz_ptr->num_prods[i], sizeof(int));
                rxn_ptr[i].numprods_made = (int *)calloc(arsz_ptr->num_prods[i], sizeof(int));
			switch (rxn_ptr[i].rxn_index) 
            {
				case BINDING:
				case UNIQUE_BI_BI:
				case UNBINDING:
				case UNI_UNI:
				case HOMO_LTOR:
				{
  	  				for (index = 0; index < arsz_ptr->num_prods[i]; index++) 
						fscanf(infile, " %d\n", &rxn_ptr[i].products[index]);
                                rxn_ptr[i].num_rates = 1; 
                    rxn_ptr[i].rates = calloc(rxn_ptr[i].num_rates , sizeof(struct rate_data));
                    fscanf(infile, "StoP = %le \n", &rxn_ptr[i].rates[0].value);
 	  	 	  	
					break;
				}

				case UNI_MULTI:
				case TRANSV1:
				{
                    for (index = 0; index < arsz_ptr->num_prods[i]; index++) 
					fscanf(infile, " %d %d\n", &rxn_ptr[i].products[index], &rxn_ptr[i].numprods_made[index]);
                                rxn_ptr[i].num_rates = 1; 
                    rxn_ptr[i].rates = calloc(rxn_ptr[i].num_rates, sizeof(struct rate_data));
                    fscanf(infile, "StoP = %le \n", &rxn_ptr[i].rates[0].value);
 	 	  	  		
					break;
				}
				case GENM:
				{
    				for (index = 0; index < arsz_ptr->num_prods[i]; index++) 
                        fscanf(infile, " %d %d\n", &rxn_ptr[i].products[index], &rxn_ptr[i].numprods_made[index]);
                                rxn_ptr[i].num_rates = arsz_ptr->num_subs[i]; 
                        rxn_ptr[i].rates = calloc(rxn_ptr[i].num_rates, sizeof(struct rate_data));
                        fscanf(infile, "StoP = %le \n", &rxn_ptr[i].rates[0].value);
    				for (index = 1; index < arsz_ptr->num_subs[i]; index++) 
                        fscanf(infile, "%le ", &rxn_ptr[i].rates[index].value);
 	 	  	  		
					break;
				}
				case NTH_ORDER:
				{
                    for (index = 0; index < arsz_ptr->num_prods[i]; index++) 
                        fscanf(infile, " %d %d\n", &rxn_ptr[i].products[index], &rxn_ptr[i].numprods_made[index]);
                                rxn_ptr[i].num_rates = 2; 
                     rxn_ptr[i].rates = calloc(rxn_ptr[i].num_rates, sizeof(struct rate_data));
                    fscanf(infile, "StoP = %le %le \n", &rxn_ptr[i].rates[0].value, &rxn_ptr[i].rates[1].value);
 	 	  	  		
					break;
				}

				case UNDEFINED:
				{
                     for (index = 0; index < arsz_ptr->num_prods[i]; index++)
                fscanf(infile, " %d %d\n", &rxn_ptr[i].products[index], &rxn_ptr[i].numprods_made[index]);
                                        fscanf(infile,"%s\n",  rxn_ptr[i].kineticlaw);
                                        fscanf(infile,"%s %d\n", junk, &rxn_ptr[i].num_rates);

                           rxn_ptr[i].rates = calloc(rxn_ptr[i].num_rates, sizeof(struct rate_data));
                                        for (index = 0; index <rxn_ptr[i].num_rates; index ++)
                           {
                 fscanf(infile,"%s %le\n",rxn_ptr[i].rates[index].name, &rxn_ptr[i].rates[index].value);
                                        }
                                   break;

				}
                                         default:
                 printf("a specified reaction type is not defined \n");
			}
		}

  		fscanf(infile, "id = %d\n\n", &rxn_ptr[i].id);

    }

	fscanf(infile,"time_start = %le\n",&r_c->time_start);
	fscanf(infile,"time_end = %le\n",&r_c->time_end);
	fscanf(infile,"volume = %le\n",&r_c->volume);
	fscanf(infile,"algorithm = %d\n",&r_c->stoch_algor);
    if (r_c->stoch_algor == 3)
       	fscanf(infile,"tau_error = %le\n",&r_c->tau_error);
   
	fscanf(infile,"randseed = %lu\n\n",&r_c->randseed);

	fscanf(infile,"num_monit = %d\n",&arsz_ptr->num_monitor);
	r_c->comps_to_mon = (int *)calloc(arsz_ptr->num_monitor, sizeof(int));
	for (i = 0; i < arsz_ptr->num_monitor; i++) {
		fscanf(infile,"%d\n",&r_c->comps_to_mon[i]);
	}
        
	fscanf(infile,"snapshot_interval = %le\n",&r_c->snapshot_interval);
	fscanf(infile,"eventlog_flag = %d\n",&r_c->evlog_flag);
	fscanf(infile, "num_repeats = %d\n", &r_c->num_repeats[0]);
    fscanf(infile,"\n");
        
        if (r_c->num_sets > 1)
        {
	    for (k = 1; k < r_c->num_sets; k++) 
             {
		fscanf(infile, "num_repeats = %d\n", &r_c->num_repeats[k]);
        	fscanf(infile, "num_species = %d\n", &sets[k].num_cmpds);  
                sets[k].cmpds = calloc(sets[k].num_cmpds, sizeof(struct cmpd_data));
                	for (index = 0; index <sets[k].num_cmpds; index ++)
                               fscanf(infile,"%d %d\n",&sets[k].cmpds[index].id, &sets[k].cmpds[index].value);
                
        	fscanf(infile, "num_rates = %d\n", &sets[k].num_rates);  
                sets[k].rxn_id = (int *)calloc(sets[k].num_rates, sizeof(int));
                sets[k].rates = calloc(sets[k].num_rates, sizeof(struct rate_data));
                	for (index = 0; index <sets[k].num_rates; index ++)
                               fscanf(infile,"%d %d %le\n",&sets[k].rxn_id[index],&sets[k].rates[index].id, &sets[k].rates[index].value);
                
            }
	}


	fclose(infile);
}
