// file: dec_read_4.cc
//

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

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: read_cd_models_cc
//
// arguments:
//  FILE* fp: (input) file pointer
//  
// return: a logical_1 indicating status
//
// this method reads in the cd model data from file into an array of
// phone objects
//
logical_1 Decoder::read_cd_models_cc(FILE* fp_a) {

  // check file
  //
  if (fp_a == (FILE*)NULL) {
    error_handler_cc((char_1*)"read_cd_models_cc",
		     (char_1*)"NULL input file pointer");
  }
  
  // allocate memory for the phone map
  //
  int_4 num_map = (int_4)pow(num_ci_d, cd_size_d);
  cdmap_d = new int_4[num_map];
  for (int_4 i = 0; i < num_map; i++) {
    cdmap_d[i] = DEC_DEFAULT_INDEX;
  }
  
  // variables to read data
  //
  int_4 ind = (int_4)0;
  int_4 mod = (int_4)0;
  int_4 nph = (int_4)0;
  int_4* mph = (int_4*)NULL;
  char_1* tmp = new char_1[ISIP_MAX_STRING_LENGTH];

  // array of phone models
  //
  int_4 phcount = (int_4)0;
  
  // read data from file
  //
  while (fscanf(fp_a, "%s", tmp) != EOF) {
    
    // ignore comment lines
    //
    if (tmp[0] == (char_1)'#') {
      
      // do nothing
      //
      fscanf(fp_a, "%[^\n]", tmp);
      fscanf(fp_a, "%[\n]", tmp);
    }

    // read the number of phones
    //
    else if (strcmp((char*)tmp, "num_phones") == 0) {
      
      // read the number of phones
      //
      fscanf(fp_a, "%s%ld", tmp, &num_cd_d);

      // but this number is valid only for cd models, if ci models are
      // used for decoding then the number of models is the same as
      // that of the ci phones
      //
      if (cd_size_d == DEC_MONOPHONE_SIZE) {
	num_cd_d = num_ci_d;
      }
      
      // allocate space for the phone list
      //
      cd_models_d = new Phone*[num_cd_d];
    }

    // otherwise read the phone data
    //
    else {
	
      // read the number of constituent monophones
      //
      fscanf(fp_a, "%ld", &nph);

      // if this is ci mode, only read monophone data
      //
      if (context_mode_d == DEC_MONO_PHONE_MODE) {

	// make sure this is monophone
	//
	if (nph == cd_size_d) {

	  // read phone data
	  //
	  mph = new int_4[nph];
	  for (int_4 j = 0; j < nph; j++) {
	    fscanf(fp_a, "%ld", &mph[j]);
	  }
      
	  // read the map index and model index
	  //
	  fscanf(fp_a, "%ld%ld", &ind, &mod);
	  
	  // create the phone
	  //
	  cd_models_d[phcount] = new Phone(tmp, nph, mph, models_d[mod]);
	  
	  // store a link to this in the phone map
	  //
	  cdmap_d[mph[nph - 1]] = phcount;
	  //	  cdmap_d[ind] = phcount;
	  
	  // increase phone count
	  //
	  phcount++;
	  
	  // free memory
	  //
	  delete [] mph;
	  mph = (int_4*)NULL;
	}

	// otherwise ignore this line of data
	//
	else {
	  fscanf(fp_a, "%[^\n]", tmp);
	  fscanf(fp_a, "%[\n]", tmp);
	}
      } // end if ci models mode

      // otherwise these are cd phone models
      //
      else {
	
	// if this is a bi-phone need special treatment wrt direction of
	// context
	//
	if (nph == (int_4)2) {
	  
	  // allocate memory
	  //
	  mph = new int_4[cd_size_d];
	  
	  // check for context direction and read the constituent
	  // monophone indices
	  //
	  if (strchr((char*)tmp, '-') != (char*)NULL) {
	    for (int_4 j = 0; j < nph; j++) {
	      fscanf(fp_a, "%ld", &mph[j]);
	    }
	    mph[nph] = (int_4)0;
	  }
	  else if (strchr((char*)tmp, '+') != (char*)NULL) {
	    for (int_4 j = 0; j < nph; j++) {
	      fscanf(fp_a, "%ld", &mph[j + 1]);
	    }
	    mph[0] = (int_4)0;
	  }
	}
	
	// otherwise treat normally
	//
	else {
	  mph = new int_4[nph];
	  for (int_4 j = 0; j < nph; j++) {
	    fscanf(fp_a, "%ld", &mph[j]);
	  }
	}
	
	// read the map index and model index
	//
	fscanf(fp_a, "%ld%ld", &ind, &mod);
	
	// create the phone
	//
	cd_models_d[phcount] = new Phone(tmp, nph, mph, models_d[mod]);
	
	// store a link to this in the phone map
	//
	cdmap_d[ind] = phcount;
	
	// increase phone count
	//
	phcount++;
	
	// free memory
	//
	delete [] mph;
	mph = (int_4*)NULL;

      } // end else cd mode
    } // end else data line
  } // end if not EOF

  // make sure there is no mismatch in number of phones
  //
  if (num_cd_d != phcount) {
    fprintf(stdout, "Error - mismatch in number of phones\n");
    exit(ISIP_PROTO_ERROR);
  }
  
  // free memory
  //
  delete [] tmp;

  // exit gracefully
  //
  return ISIP_TRUE;
}
