// file: ht_print_0.cc
//

// isip include files
//
#include "hmm_train.h"
#include "hmm_train_constants.h"

// method: print_hyps_cc
//
// arguments:
//  int_4 hyps : (input) number of hypotheses
//  char_1* file : (input) name of output file
//  Train_Trace** array : (input) array of nbest hypotheses
//  int_4 frame_a : (input) the current frame index
//  Train_Phone** phones : (input) list of phone models
//  int_4 ph_size : (input) size of phone context
//  int_4* ngen : (input) number of traces generated
//  int_4* ndel : (number of traces deleted
//  int_4* ntr : (output) total number of active traces
//
// return: a logical_1 flag indicating success
//
// this method dumps the n-best hypotheses to the output file
//
logical_1 print_hyps_cc(int_4 hyps_a, char_1* file_a, Train_Trace** array_a,
			int_4 frame_a, Train_Phone** phones_a, int_4 ph_size_a,
			int_4* ngen_a, int_4* ndel_a, int_4* ntr_a) {
  
  // dummy variables
  //
  Train_Trace* tr = (Train_Trace*)NULL;
  Train_Trace* btr = (Train_Trace*)NULL;
  Train_Trace** back = (Train_Trace**)NULL;

  Train_Word* word = (Train_Word*)NULL;
  Train_Phone* phone = (Train_Phone*)NULL;
  Train_Link_list* trlist = (Train_Link_list*)NULL;
  
  int_4 frm = (int_4)0;
  int_4 pfrm = (int_4)0;
  
  float_8 score = (float_8)0;
  float_8 presc = (float_8)0;
  float_8 wdsc = (float_8)0;

  int_4 phn = (int_4)0;
  Train_Lex_node* lex_node = (Train_Lex_node*)NULL;
  Train_Lattice_node* lat_node = (Train_Lattice_node*)NULL;

  int_4 level = HT_WORD_LEVEL;

  // print the n-best list of word-hypotheses to file
  //
  FILE* fp = fopen((char*)file_a, "w");
  if (fp == (FILE*)NULL) {
    fprintf(stdout, "Cannot open output file %s\n", file_a);
    exit(ISIP_PROTO_ERROR);
  }
  
  // output the number of traces
  //
  fprintf(fp, "%-8s = %8ld\n\n", "Time", frame_a);
  fprintf(fp, "%16s %8s %8s %8s\n", "Train_Word", "Train_Phone", "Train_State", "Total");
  fprintf(fp, "%-8s %8ld %8ld %8ld %8ld\n", "Live", ntr_a[HT_WORD_LEVEL],
	  ntr_a[HT_PHONE_LEVEL], ntr_a[HT_STATE_LEVEL],
	  ntr_a[HT_WORD_LEVEL] + ntr_a[HT_PHONE_LEVEL] +
	  ntr_a[HT_STATE_LEVEL]);
  fprintf(fp, "%-8s %8ld %8ld %8ld %8ld\n", "New", ngen_a[HT_WORD_LEVEL],
	  ngen_a[HT_PHONE_LEVEL], ngen_a[HT_STATE_LEVEL],
	  ngen_a[HT_WORD_LEVEL] + ngen_a[HT_PHONE_LEVEL] +
	  ngen_a[HT_STATE_LEVEL]);
  fprintf(fp, "%-8s %8ld %8ld %8ld %8ld\n", "Deleted", ndel_a[HT_WORD_LEVEL],
	  ndel_a[HT_PHONE_LEVEL], ndel_a[HT_STATE_LEVEL],
	  ndel_a[HT_WORD_LEVEL] + ndel_a[HT_PHONE_LEVEL] +
	  ndel_a[HT_STATE_LEVEL]);
  
  // print the n-best word hypotheses
  //
  for (int_4 ff = 0; ff < hyps_a; ff++) {

    // initialize variables
    //
    trlist = new Train_Link_list();
    score = (float_8)0;
    presc = (float_8)0;
    wdsc = (float_8)0;
    frm = (int_4)0;
    pfrm = (int_4)0;

    // put the traces in the right order
    //
    for (tr = array_a[ff]; tr != (Train_Trace*)NULL; tr = btr) {
      trlist->insert_cc(tr);
      back = tr->get_back_ptr_cc();
      if (back != (Train_Trace**)NULL) {
	btr = back[0];
      }
      else {
	break;
      }
    }

    // now loop again and output data
    //
    Train_Link_node* nd = trlist->get_curr_cc(); 
    while (nd != (Train_Link_node*)NULL) {

      // get the trace
      //
      tr = (Train_Trace*)(nd->get_item_cc());

      // get the trace params
      //
      frm = tr->get_frame_ind_cc();

      // make sure this is not start trace
      //
      if (frm > (int_4)0) {

	// get the params
	//
	score = tr->get_score_cc();

	lat_node = tr->get_lat_node_cc();
	lex_node = tr->get_lex_node_cc();
	phn = lex_node->get_phone_cc();
	
	level = tr->get_level_cc();

	// if this is at the state level
	//
	if (level == HT_STATE_LEVEL) {
	  
	  // print state-level data
	  //
	  fprintf(fp, "\n%.4ld %.4ld %.6f s%-3ld", pfrm, frm,
		  score - presc, (int_4)(tr->get_state_ind_cc()));
	  presc = score;
	  pfrm = frm;
	}
	
	// if this is at the phone level
	//
	if (level == HT_PHONE_LEVEL) {
	  
	  // get the phone information
	  //
	  phone = phones_a[tr->get_phone_ind_cc()];
	  
	  // print phone-level data
	  //
	  fprintf(fp, "\n%.4ld %.4ld %.6f %-12s", pfrm, frm, score - presc,
		  phone->get_name_cc());
	  presc = score;
	  pfrm = frm;
	}
	
	// if this is at the word level
	//
	if (level == HT_WORD_LEVEL) {

	  // also get word info
	  //
	  word = lat_node->get_word_cc();
	  
	  // print the word info
	  //
	  fprintf(fp, " %-20s %.6f %.6f", word->get_name_cc(),
		  score - presc, score - wdsc);
	  presc = score;
	  wdsc = score;
	  pfrm = frm;
	}
      } // end if frm > 0

      // the previous node in the list
      //
      nd = nd->get_prev_cc();
    }
    
    // print new line
    //
    fprintf(fp, "\n");

    // free memory
    //
    delete trlist;
    trlist = (Train_Link_list*)NULL;
  }

  // close file
  //
  fclose(fp);

  // exit gracefully
  //
  return ISIP_TRUE;
}
