// file: ht_phone_3.cc
//

// system include files
//
#include <memory.h>

// isip include files
//
#include "hmm_train.h"
#include "hmm_train_constants.h"
 
// method: read_phones_cc
//
// arguments:
//  int_4 num_mono : (input) number of monophones
//  int_4 ph_size : (input) size of phone context
//  Train_Model** models : (input) array of model pointers
//  int_4*& ph_map : (output) map of triphones to phone models
//  int_4& num_ph : (output) number of phones
//  char_1* file : (input) data file name
//  int_4*& mod_map : (output) map of models to array of model objects
//  int_4 context_mode : (input) the context mode
//  int_4& sp_phn_ind : (output) phone index of sp
//  
// return: a Train_Phone** pointing to a list of phone models
//
Train_Phone** read_new_phones_cc(int_4 num_mono_a, int_4 ph_size_a, Train_Model** models_a,
			   int_4*& ph_map_a, int_4& num_ph_a, char_1* file_a,
			   int_4*& mod_map_a, int_4 context_mode_a,
			   int_4& sp_phn_ind_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);
  }

  // allocate memory for the phone map
  //
  int_4 size = (int_4)pow(num_mono_a, ph_size_a);
  ph_map_a = new int_4[(int_4)pow(num_mono_a, ph_size_a)];
  // memset(ph_map_a, 0, size * sizeof(int_4));
  for (int_4 i = 0; i < size; i++) {
    ph_map_a[i] = (int_4)0;
  }
  
  // variables to read data
  //
  char_1* tmp = new char_1[ISIP_MAX_STRING_LENGTH];
  int_4 ind = (int_4)0;
  int_4 mod = (int_4)0;
  logical_1 number_flag = ISIP_FALSE;

  int_4 nph = (int_4)0;
  int_4* mph = (int_4*)NULL;
  
  Train_Phone** phones = (Train_Phone**)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 phone data
    //
    else if (strcmp((char*)tmp, (char*)HT_STR_NUM_PHONES) == 0) {

      // change the flag
      //
      number_flag = ISIP_TRUE;
      
      // read the number of phones
      //
      fscanf(fp, "%s%ld", tmp, &num_ph_a);
      
      // allocate space for the phone list
      //
      phones = new Train_Phone*[num_ph_a];
      mod_map_a = new int_4[num_ph_a];
      
      // now read the phone data
      //
      for (int_4 i = 0; i < num_ph_a; i++) {

	// reset the temporary buffer
	//
	tmp = (char_1*)memset(tmp, (int_4)0, ISIP_MAX_STRING_LENGTH);
	
	// read the phone string and the number of constituent monophones
	//
	fscanf(fp, "%s%ld", tmp, &nph);

	// get the sp phone index
	//
	if (strcmp((char*)tmp, (char*)HT_SP_STRING) == 0) {
	  sp_phn_ind_a = i;
	}

	// for word internal mode
	//
	if ((nph == (int_4)2) && (context_mode_a == 2)){
	  mph = new int_4[3];
	  for (int_4 i = 0; i < 10; i++) {
	    if (tmp[i] == '-') {
	      for (int_4 j = 0; j < 2; j++) {
		fscanf(fp, "%ld", &mph[j]);
	      }
	      mph[2] = 0;
	    }
	    else if (tmp[i] == '+') {
	      for (int_4 j = 1; j < 3; j++) {
		fscanf(fp, "%ld", &mph[j]);
	      }
	      mph[0] = 0;
	    }
	  }
	}

	else {
	  
	  // read the constituent monophone indices
	  //
	  mph = new int_4[nph];
	  for (int_4 j = 0; j < nph; j++) {
	    fscanf(fp, "%ld", &mph[j]);
	  }
	}
	// read the map index and model index
	//
	fscanf(fp, "%ld%ld", &ind, &mod);
        mod_map_a[i] = mod;
	
	// create the phone
	//
	phones[i] = new Train_Phone(tmp, nph, mph, models_a[mod]);

	// store a link to this in the phone map
	//
	ph_map_a[ind] = i;

	// free memory
	//
	delete [] mph;
	mph = (int_4*)NULL;
      }
    }
  }

  // check the flag
  //
  if (number_flag == ISIP_FALSE) {
    fprintf(stdout, "Error : no number of phones specified in %s\n",
	    (char*)file_a);
    exit(ISIP_PROTO_ERROR);
  }
  
  // close file
  //
  fclose(fp);
    
  // free memory
  //
  delete [] tmp;
  
  // exit gracefully
  //
  return phones;
}
