// file: cmmf_read_1.cc
//

// isip include files
//
#include "convert_mmf.h"
#include "convert_mmf_constants.h"

// method: read_states_ascii_cc
//
// arguments:
//  int_4& num_st : (output) number of states
//  int_4& num_feat : (output) number of features in data vector
//  char_1* file : (input) data file name
//  
// return: a State** pointing to a list of States
//
// this method reads the State models from file --- each mixture
// component in the States is assumed to have a diagonal covariance
// matrix
//
Train_State** read_states_ascii_cc(int_4& num_st_a, int_4& num_feat_a,
			     char_1* file_a) {
  
  // open file
  //
  FILE* fp = fopen((char*)file_a, "r");
  if (fp == (FILE*)NULL) {
    fprintf(stdout, "cannot open file %s\n", file_a);
    exit(ISIP_PROTO_ERROR);	
  }	
  
  // variables to read data
  //
  char_1* tmp = new char_1[ISIP_MAX_STRING_LENGTH];
  int_4 ind = (int_4)0;
  int_4 mix_ind = (int_4)0;
  logical_1 number_flag = ISIP_FALSE;
  logical_1 size_flag = ISIP_FALSE;
  
  int_4 num_mix = (int_4)0;
  float_4* weights = (float_4*)NULL;
  float_4* scale = (float_4*)NULL;
  float_4** mean = (float_4**)NULL;
  float_4** covar = (float_4**)NULL;
  
  Train_State** states = (Train_State**)NULL;
  
  // read data from file
  //
  while (fscanf(fp, "%s", tmp) != EOF) {
    
    // ignore comment lines
    //
    if (tmp[0] == (char_1)'#') {
      
      // do nothing
      //
      fscanf(fp, "%[^\n]", tmp);
      fscanf(fp, "%[\n]", tmp);
    }
    
    // read the size of the feature vector
    //
    else if (strcmp((char*)tmp, (char*)CMMF_STR_FEATURE_SIZE) == 0) {
      
      // change the flag
      //
      size_flag = ISIP_TRUE;
      
      fscanf(fp, "%s", tmp);
      fscanf(fp, "%ld", &num_feat_a);
      
      // set the feature size
      //
      Train_State::set_num_features_cc(num_feat_a);
    }
    
    // read the number of states
    //
    else if (strcmp((char*)tmp, (char*)CMMF_STR_NUM_STATES) == 0) {
      
      // change the flag
      //
      number_flag = ISIP_TRUE;
      
      // check the flag
      //
      if (size_flag == ISIP_FALSE) {
	fprintf(stdout, "Error : no size of feature specified in %s\n",
		(char*)file_a);
	exit(ISIP_PROTO_ERROR);
      }
      
      fscanf(fp, "%s", tmp);
      fscanf(fp, "%ld", &num_st_a);
      
      // allocate space for the Train_States list
      //
      states = new Train_State*[num_st_a];
      
      // now read the Train_State data
      //
      for (int_4 i = 0; i < num_st_a; i++) {
	
	// read the Train_State index
	//
	fscanf(fp, "%s%ld", tmp, &ind);
	
	// read the number of mixtures
	//
	fscanf(fp, "%s%ld", tmp, &num_mix);
	
	if (num_mix > 0) {
	  
	  // allocate and initialize the state parameters
	  //
	  weights = new float_4[num_mix];
	  scale = new float_4[num_mix];
	  mean = new float_4*[num_mix];
	  covar = new float_4*[num_mix];
	  
	  // read data for each mixture
	  //
	  for (int_4 j = 0; j < num_mix; j++) {
	    
	    // read mixture index
	    //
	    fscanf(fp, "%s%ld", tmp, &mix_ind);
	    
	    // read the mixture weight
	    //
	    fscanf(fp, "%s%f", tmp, &weights[j]);
	    
	    // allocate space and read the mean vector
	    //
	    mean[j] = new float_4[num_feat_a];
	    fscanf(fp, "%s", tmp);
	    for (int_4 k = 0; k < num_feat_a; k++) {
	      fscanf(fp, "%f", &mean[j][k]);
	    }
	    
	    // allocate space and read the covar matrix
	    //
	    covar[j] = new float_4[num_feat_a];
	    fscanf(fp, "%s", tmp);
	    for (int_4 k = 0; k < num_feat_a; k++) {
	      fscanf(fp, "%f", &covar[j][k]);
	    }
	    
	    // read the scale factor
	    //
	    fscanf(fp, "%s%f", tmp, &scale[j]);
	  }
	  
	  
	  // create the state
	  //
	  states[ind] = new Train_State();
	  states[ind]->set_num_mixtures_cc(num_mix);
	  states[ind]->set_weights_cc(weights);
	  states[ind]->set_scale_cc(scale);
	  states[ind]->set_covar_cc(covar);
	  states[ind]->set_mean_cc(mean);
	
	
	  // free memory
	  //
	  for (int_4 kl = 0; kl < num_mix; kl++) {
	    delete [] mean[kl];
	  }
	  delete [] mean;
	  for (int_4 kl = 0; kl < num_mix; kl++) {
	    delete [] covar[kl];
	  }
	  delete [] covar;
	  delete [] scale;
	  delete [] weights;
	}
      }
    }
  }
  
  if (number_flag == ISIP_FALSE) {
    fprintf(stdout, "Error : no number of states specified in %s\n",
	    (char*)file_a);
    exit(ISIP_PROTO_ERROR);
  }
  
  // close file
  //
  fclose(fp);
  
  // free memory
  //
  delete [] tmp;
  
  // exit gracefully
  //
  return states;
}
