// file: dec_write_0.cc
//

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: write_output_cc
//
// arguments:
//  FILE* fp: (input) output file pointer
//
// return: logical_1 indicating status
//
// this method writes the decoder output hypothesis to file
//
logical_1 Decoder::write_output_cc(FILE* fp_a) {
  
  // check file
  //
  if (fp_a == (FILE*)NULL) {
    error_handler_cc((char_1*)"write_output_cc",
                     (char_1*)"NULL input file pointer");
  }

  // dummy variables
  //
  int_4 state = (int_4)1;
  int_4 old_state = (int_4)1;
  Word* word = (Word*)NULL;
  Phone* phone = (Phone*)NULL;
  History* hist = (History*)NULL;
  void_p hnode = (void_p)NULL;
  Link_list* pathlist = (Link_list*)NULL;
  Link_list* histlist = (Link_list*)NULL;
  char_1* wdname = (char_1*)NULL;
  
  int_4 frm = (int_4)0;
  int_4 pfrm = (int_4)0;
  int_4 lev = DEC_WORD_LEVEL;
  float_4 score = (float_4)0;
  float_4 prev_score = (float_4)0;
  float_4 stsc = (float_4)0;
  float_4 phsc = (float_4)0;
  float_4 wdsc = (float_4)0;
  logical_1 htype = HISTORY_WORDGRAPH;
  int_4 start_frame = (int_4)0;
  int_4 end_frame = (int_4)0;

  // store the position of the output file end
  //
  int_4 end_pos = ftell(fp_a);
  
  // go to the beginning of the file
  //
  rewind(fp_a);
  
  // output the number of traces if demo mode
  //
  if (demo_mode_d == ISIP_TRUE) {
    fprintf(fp_a, "%-8s = %8ld\n\n", "Time", frame_d);
    fprintf(fp_a, "%16s %8s %8s %8s\n", "Word", "Phone", "State", "Total");
    fprintf(fp_a, "%-8s %8ld %8ld %8ld %8ld\n", "Live",
	    num_traces_total_d[DEC_WORD_LEVEL],
	    num_traces_total_d[DEC_MODEL_LEVEL],
	    num_traces_total_d[DEC_STATE_LEVEL],
	    num_traces_total_d[DEC_WORD_LEVEL] +
	    num_traces_total_d[DEC_MODEL_LEVEL] +
	    num_traces_total_d[DEC_STATE_LEVEL]);
    fprintf(fp_a, "%-8s %8ld %8ld %8ld %8ld\n", "New",
	    total_gen_d[DEC_WORD_LEVEL],
	    total_gen_d[DEC_MODEL_LEVEL],
	    total_gen_d[DEC_STATE_LEVEL],
	    total_gen_d[DEC_WORD_LEVEL] +
	    total_gen_d[DEC_MODEL_LEVEL] +
	    total_gen_d[DEC_STATE_LEVEL]);
    fprintf(fp_a, "%-8s %8ld %8ld %8ld %8ld\n", "Deleted",
	    total_del_d[DEC_WORD_LEVEL],
	    total_del_d[DEC_MODEL_LEVEL],
	    total_del_d[DEC_STATE_LEVEL],
	    total_del_d[DEC_WORD_LEVEL] +
	    total_del_d[DEC_MODEL_LEVEL] +
	    total_del_d[DEC_STATE_LEVEL]);
  }
  
  // print the n-best word hypotheses
  //
  for (int_4 ff = 0; ff < num_hyps_d; ff++) {

    // initialize variables
    //
    pathlist = new Link_list();
    score = (float_4)0;
    stsc = (float_4)0;
    phsc = (float_4)0;
    wdsc = (float_4)0;
    frm = (int_4)0;
    pfrm = (int_4)0;

    // put the histories in the right order
    //
    hist = nbest_d[ff]->get_hist_cc();
    pathlist->insert_cc(hist);
    histlist = hist->get_prev_list_cc();
    
    // go over the whole path
    //
    while (histlist != (Link_list*)NULL) {
      
      // get the history node
      //
      hist = (History*)(histlist->get_head_cc()->get_item_cc());
      pathlist->insert_cc(hist);
      
      // get the previous history
      //
      histlist = hist->get_prev_list_cc();
    }

    // now loop again and output data
    //
    for (Link_node* nd = pathlist->get_curr_cc(); nd != (Link_node*)NULL;
	 nd = nd->get_prev_cc()) {

      // get the history node here
      //
      hist = (History*)(nd->get_item_cc());

      // make sure this is not start trace
      //
      if (hist->get_prev_list_cc() != (Link_list*)NULL) {
	
	// get the trace params
	//
	frm = hist->get_frame_ind_cc();
	lev = hist->get_level_cc();
	score = hist->get_score_cc();
	hnode = hist->get_histwords_cc((int_4)0);
	htype = hist->get_type_cc();
	
	// if this is at the state level
	//
	if (lev == DEC_STATE_LEVEL) {

	  // get the state information
	  //
	  state = hist->get_state_ind_cc();
	  
	  // if state-level alignment is required
	  //
	  if (align_mode_d == DEC_STATE_ALIGN_MODE) {

	    // print state-level data and update values
	    //
	    fprintf(fp_a, "\n%.4ld %.4ld %.6f s%-2ld", pfrm, frm,
		    score - stsc, state);
	    
	    stsc = score;
	    pfrm = frm;
	  }
	  
	  else if (align_mode_d == DEC_STATE_ALIGN_MODE) {
	    stsc = score;
	    pfrm = frm;
	    if (state != old_state) {
	      fprintf(fp_a, "\n%.4ld %.4ld %.6f s%-2ld", start_frame,
		      end_frame, score - prev_score, old_state);
	      start_frame = end_frame;
	      prev_score = score;
	    }
	    end_frame = frm;
	    old_state = state;
	  }
	} // end if state level history
	
	// if this is at the phone level
	//
	else if (lev == DEC_MODEL_LEVEL) {
	  
	  // get the phone information
	  //
	  phone = cd_models_d[hist->get_phone_ind_cc()];

	  // print phone-level data and update values
	  //
	  if (align_mode_d == DEC_MODEL_ALIGN_MODE) {
	    fprintf(fp_a, "\n%.4ld %.4ld %-9s %.6f", pfrm, frm,
		    phone->get_name_cc(), score - phsc);
	    stsc = score;
	    phsc = score;
	    pfrm = frm;
	  }
	  
	  else if (align_mode_d == DEC_STATE_ALIGN_MODE) {
	    fprintf(fp_a, " %-9s %.6f %.6f", phone->get_name_cc(),
		    score - stsc, score - phsc);
	    stsc = score;
	    phsc = score;
	    pfrm = frm;
	  }	  
	}
	
	// if this is at the word level
	//
	else if (lev == DEC_WORD_LEVEL) {
	  
	  // get the word information
	  //
	  if (htype == HISTORY_WORDGRAPH) {
	    word = ((Lattice_node*)hnode)->get_word_cc();
	  }
	  else if (htype == HISTORY_NGRAM) {
	    word = ((Ngram_node*)hnode)->get_word_cc();
	  }
	  
	  // print word-level data and update values
	  //
	  if (word != (Word*)NULL) {

	    // get the word string
	    //
	    wdname = word->get_name_cc();

	    // do not output anything for special words, only adjust
	    // timestamps
	    //
	    if (*wdname != ISIP_DOLLAR) {

	      // output appropriate word string
	      //
	      if (align_mode_d == DEC_WORD_ALIGN_MODE) {
		fprintf(fp_a, "\n%.4ld %.4ld %-14s %.6f", pfrm, frm, wdname,
			score - wdsc);
	      }
	      else {
		fprintf(fp_a, " %-14s %.6f %.6f", wdname, score - stsc,
			score - wdsc);
	      }

	      // update data
	      //
	      stsc = score;
	      phsc = score;
	      wdsc = score;
	      pfrm = frm;
	      prev_score = score;
	    }
	  } // end if word is not null
	} // end else if word level
      } // end if frm > 0
    } // end loop over all nodes
    
    // print new line
    //
    fprintf(fp_a, "\n");
    
    // free memory
    //
    delete pathlist;
    pathlist = (Link_list*)NULL;
  }

  // clear the old data until the end of the output file
  //
  while (ftell(fp_a) < end_pos) {
    fprintf(fp_a, " ");
  }
  
  // flush the output
  //
  fflush(fp_a);
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
