// file: itri_model_0.cc
//
// isip include files
//
#include "init_triphones.h"
#include "init_triphones_constants.h"
 
// method: read_models_cc
//
// arguments:
//  FILE* file : (input) data file name
//  State** states : (input) the array of states
//  float_4*** trans : (input) the array of transition matrices
//  Train_Hash_table*& trans_map : (output) map between model name and
//                                 transition index
//  int_4& num_mod : (output) number of models
//  
// return: a Train_Hash_table* which hashes the models based on their
//         phone symbol
//
Train_Hash_table* read_models_cc(FILE* file_a, Train_State** states_a,
				 float_4*** trans_a,
				 Train_Hash_table*& trans_map_a,
				 int_4& num_mod_a) {
  
  // variables to read data
  //
  char_1* tmp = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* name = new char_1[ISIP_MAX_STRING_LENGTH];
  int_4 ind = (int_4)0;
  logical_1 number_flag = ISIP_FALSE;
  
  int_4 num_states = (int_4)0;
  int_4 trans_ind = (int_4)0;
  int_4 state_ind = (int_4)0;
  
  Train_State** state_list = (Train_State**)NULL;
  Train_Model** models = (Train_Model**)NULL;
  Train_Hash_table* phone_table = (Train_Hash_table*)NULL;
    
  // define the hash table to hold the monophone information and transition
  // information
  //
  phone_table = new Train_Hash_table(TRAIN_HASH_TABLE_SIZE);
  trans_map_a = new Train_Hash_table(TRAIN_HASH_TABLE_SIZE);
  Train_Hash_cell* ph_cell = (Train_Hash_cell*)NULL;
  Train_Hash_cell* tr_cell = (Train_Hash_cell*)NULL;
  
  // define memory manager
  //
  Train_Memory_manager* manager = Train_Link_list::get_manager_cc(); 

  // read data from file
  //
  while (fscanf(file_a, "%s", tmp) != EOF) {
    
    // ignore comment lines
    //
    if (tmp[0] == (char_1)'#') {
      
      // do nothing
      //
      fscanf(file_a, "%[^\n]", tmp);
      fscanf(file_a, "%[\n]", tmp);
    }
    
    // read the model data
    //
    else if (strcmp((char*)tmp, (char*)ITRI_STR_NUM_MODELS) == 0) {

      // change the flag
      //
      number_flag = ISIP_TRUE;
      
      // read the number of models
      //
      fscanf(file_a, "%s%ld", tmp, &num_mod_a);
      
      // allocate space for the model list
      //
      models = new Train_Model*[num_mod_a];
      
      // now read the model data
      //
      for (int_4 i = 0; i < num_mod_a; i++) {
	
	// read the model index
	//
	fscanf(file_a, "%s%ld", tmp, &ind);
	
	// read the model string
	//
	fscanf(file_a, "%s%s", tmp, name);
	
	// read the number of states
	//
	fscanf(file_a, "%s%ld", tmp, &num_states);
	
	// allocate memory for the data
	//
	state_list = new Train_State*[num_states];
	
	// read the transitions
	//
	fscanf(file_a, "%s%ld", tmp, &trans_ind);

	// put the transition index in the hash table	
	//	
	tr_cell = manager->new_hash_cc();
	tr_cell->set_cc(name, (void_p)trans_ind);
	trans_map_a->hash_insert_cc(tr_cell);
	
	// read the states
	//
	fscanf(file_a, "%s", tmp);
	for (int_4 j = 0; j < num_states; j++) {
	  
	  // read the state index
	  //
	  fscanf(file_a, "%ld", &state_ind);
	  
	  // add to the state array
	  //
	  if (state_ind == 0) {
	    state_list[j] = (Train_State*)NULL;
	  }
	  else {
	    state_list[j] = states_a[state_ind];
	  }
	}

	// create the model
	//
	models[ind] = new Train_Model(num_states, trans_a[trans_ind],
				      state_list);

	// put the model in the hash table       
	//
	ph_cell = manager->new_hash_cc();
	ph_cell->set_cc(name, (void_p)models[ind]);
	phone_table->hash_insert_cc(ph_cell);
	
	// free memory
	//
	delete [] state_list;
	state_list = (Train_State**)NULL;
      }
    }
  }

  // check the flag
  //
  if (number_flag == ISIP_FALSE) {
    fprintf(stdout, "Error : no number of models specified.\n");
    exit(ISIP_PROTO_ERROR);
  }

  // free memory
  //
  delete [] tmp;
  delete [] name;

  // free memory
  //
  delete [] models;
  models = (Train_Model**)NULL;
  
  // exit gracefully
  //
  return phone_table;
}
