// file: bw_print_1.cc
//
// isip include files
//
#include "bw_train.h"
#include "bw_train_constants.h"

// method: print_trans_cc
//
// arguments:
//  char_1* file : (output) the new transitions file
//  int_4 num_trans : (input) the number of transitions matrix
//  int_4* trans_size : (input) size of each transition matrix
//  float_8*** transitions : (input) the updated transitions matrixes
//  float_4*** old_transitions : (input) the old transitions matrixes
//  Model** models : (input) the models
//  int_4* model_access_counts : (input) the number of times each model was
//                               accessed
//  int_4 num_models : (input) the number of models
//  int_4 min_count : (input) the minimum number of times a model must occur
//                    for its states to be updated
//
// return: a logical flag to indicate success
//

// this method writes the new transition file
//
logical_1 print_trans_cc(char_1* file_a, int_4 num_trans_a,
			 int_4* trans_size_a, float_8*** transitions_a,
			 float_4*** old_transitions_a, Train_Model** models_a,
			 int_4* model_access_counts_a, int_4 num_models_a,
			 int_4 min_count_a) {

  // local variables
  //
  float_8 sum_trans = (float_8)1.0;

  // open the file
  //
  FILE* fp = fopen((char*)file_a, "w");
  if (fp == (FILE*) NULL) {
    fprintf(stdout,"Unable to open transitions file %s", file_a);
    return ISIP_FALSE;
  }

  logical_1* update_trans = new logical_1[num_trans_a];
  for (int_4 i = 0; i < num_trans_a; i++) {
    update_trans[i] = ISIP_FALSE;
  }
  
  // loop over each model's transitions and see if they need to be updated
  //
  for (int_4 mod_num = 0; mod_num < num_models_a; mod_num++) {

    // check if the model has been accessed required number of
    // times
    //
    if (model_access_counts_a[mod_num] >= min_count_a) {
      
      Train_Model* this_model = models_a[mod_num];
      
      // get the transitions for this model
      //
      float_4** this_trans = this_model->get_transitions_cc();
	
      // find these transitions in the trans list
      //
      int_4 i = 0;
      for (i = 0; i < num_trans_a; i++) {
	if (old_transitions_a[i] == this_trans) {
	  break;
	}
      }
	
      if ((i >= 0)  && (i < num_trans_a)) {
	update_trans[i] = ISIP_TRUE;
      }
    }
  }
  
  // output the number of transition
  //
  fprintf(fp, "\n");
  fprintf(fp, "num_transitions = %ld\n\n", num_trans_a);
  
  // output all of the transition matrices
  //
  for (int_4 i = 0; i < num_trans_a; i++) {
    fprintf(fp, "%ld. %ld\n", i, trans_size_a[i]);
    for (int_4 j = 0; j < trans_size_a[i]; j++) {
      sum_trans = (float_8)0.0;
      for (int_4 k = 0; k < trans_size_a[i]; k++) {
	if (transitions_a[i][j][k] > (float_8)0.0) {
	  sum_trans += transitions_a[i][j][k];
	}
      }
      for (int_4 k = 0; k < trans_size_a[i]; k++) {

	// make sure that the accumulated transitions sum up to (almost)
	// 1.0 - the almost is because they are float_8s. if they don't
	// sum up to 1.0 then just replicate the old transition matrix
	//
	if ((sum_trans > (float_8)(0.0)) && (update_trans[i] == ISIP_TRUE)) {
	  fprintf(fp, " %e", transitions_a[i][j][k]/sum_trans);
	}
	else {
	  fprintf(fp, " %e", exp(old_transitions_a[i][j][k]));
	}
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
  
  fclose(fp);

  // clean up memory
  //
  delete [] update_trans;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
