// file: init_hmm.cc
// 

// isip include files
//
#include "init_hmm.h"
#include "init_hmm_constants.h"

// main program
//
int main(int_4 argc, char_1** argv) {
  
  // variables to hold commandline parameters
  //
  char_1* input_file = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* state_file = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* models_file = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* trans_file = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* vfloor_file = new char_1[ISIP_MAX_STRING_LENGTH];

  // number of states
  //
  int_4 states = (int_4)0;
  int_4 total_num_states = (int_4)0;
  int_4* num_states = new int_4[IH_MAX_NUM_MODELS];
  int_4 num_models = (int_4)0;
  int_4 mode = (int_4)0;
  float_4 var_floor = (float_4)0;
  int_4 num_feat = IH_DEF_VEC_DIMEN;
  int_4 delta_win = IH_DEF_DELTA_WIN;
  logical_1 delta = IH_DEF_DELTA;
  logical_1 acc = IH_DEF_ACC;
  logical_1 feature_format = IH_DEF_FEATURE_FORMAT;
  
  // read and decipher the commandline
  //
  read_cmdline_cc(argc, argv, input_file, state_file, trans_file,
		  models_file, vfloor_file, mode, num_feat, var_floor,
		  delta, acc, delta_win, feature_format);
  
  // open the files containing the lists of input files, outputs repectively
  //
  FILE* fin = fopen((char*)input_file, "r");
  if (fin == (FILE*)NULL) {
    fprintf(stdout, "Error : cannot open input file %s\n", input_file);
    exit(ISIP_PROTO_ERROR);
  }
  
  FILE* fst = fopen((char*)state_file, "w");
  if (fst == (FILE*)NULL) {
    fprintf(stdout, "Error : cannot open state file %s\n", state_file);
    exit(ISIP_PROTO_ERROR);
  }

  FILE* fvar = fopen((char*)vfloor_file, "w");
  if (fvar == (FILE*)NULL) {
    fprintf(stdout, "Error : cannot open variance floor file %s\n",
	    vfloor_file);
    exit(ISIP_PROTO_ERROR);
  }

  FILE* ftr = fopen((char*)trans_file, "w");
  if (ftr == (FILE*)NULL) {
    fprintf(stdout, "Error : cannot open transition file %s\n", trans_file);
    exit(ISIP_PROTO_ERROR);
  }

  // compute the required number of feature dimensions
  //
  if (acc == ISIP_TRUE) {
    num_feat = num_feat * 3;
  }
  
  else if (delta == ISIP_TRUE) {
    num_feat = num_feat * 2;
  }
  
  // read the models file and find the number of models and number of states
  // required
  //
  FILE* fml = fopen((char*)models_file, "r");
  if (fml == (FILE*)NULL) {
    fprintf(stdout, "Error : cannot open models file %s\n", models_file);
    exit(ISIP_PROTO_ERROR);
  }
  while (fscanf(fml, "%ld %*s\n", &states) != EOF) {

    // take into account the dummy start and end states
    //
    num_states[num_models] = states+2;    
    num_models++;
    total_num_states += states;
  }
  
  float_4* means = new float_4[num_feat];
  float_4** covar = new float_4*[num_feat];
  for (int_4 i = 0; i < num_feat; i++) {
    covar[i] = new float_4[num_feat];
  }
  float_4*** trans = new float_4**[num_models];

  for (int_4 i = 0; i < num_models; i++) {
    trans[i] = new float_4*[num_states[i]];
    for (int_4 j = 0; j < num_states[i]; j++) {
      trans[i][j] = new float_4[num_states[i]];
    }
  }
  
  // initialize the means and covars
  //
  memset(means, 0, num_feat * sizeof(float_4));
  
  for (int_4 i = 0; i < num_feat; i++) {
    for (int_4 j = 0; j < num_feat; j++) {
      covar[i][j] = 0.0;
    }
  }

  for (int_4 i = 0; i < num_models; i++) {
    for (int_4 j = 0; j < num_states[i]; j++) {
      for (int_4 k = 0; k < num_states[i]; k++) {
	trans[i][j][k] = 0.0;
      }
    }
  }
    
  // compute the mean of the vectors in all mfcc files
  //
  compute_cc(fin, means, covar, num_feat, mode, delta, acc, delta_win,
	     feature_format);

  // initialize the transition file
  //
  init_trans_cc(trans, num_models, num_states);
  
  // print the results to the output file
  //
  print_state_cc(fst, fvar, means, covar, num_feat, total_num_states,
		 var_floor);
  print_trans_cc(ftr, trans, num_models, num_states);

  // free memory
  //
  fclose(fin);
  fclose(fml);
  fclose(fst);
  fclose(ftr);
  fclose(fvar);
  
  delete [] input_file;
  delete [] models_file;
  delete [] state_file;
  delete [] trans_file;
  delete [] vfloor_file;

  delete [] means;
  for (int_4 l = 0; l < num_feat; l++) {
    delete [] covar[l];
  }
  delete [] covar;

  for (int_4 i = 0; i < num_models; i++) {
    for (int_4 j = 0; j < num_states[i]; j++) {
      delete [] trans[i][j];
    }
    delete [] trans[i];
  }
  delete [] trans;
  delete [] num_states;

  // exit gracefully
  //
  exit(ISIP_NO_ERROR);
}
