// file: tr_lat_write_0.cc
//

// isip include files
//
#include "train_lattice.h"
#include "train_lattice_constants.h"

// method: write_Train_Lattice_cc
//
// arguments:
//
//  FILE* fp_out_a: (output) output Train_Lattice file
//
// return: a logical_1 indicating status
//
// this method write a Train_Lattice into a file
//
logical_1 Train_Lattice::write_lattice_cc(FILE* fp_lat_a) {
  
  // local variables
  //
  Train_Lattice_node* start_latn = start_node_d;
  Train_Lattice_node* end_latn = (Train_Lattice_node*)NULL;
  Train_Link_list* nodes_list = (Train_Link_list*)NULL;

  // initialize a list of Train_Lattice nodes
  //
  Train_Lattice_node** lnodes = (Train_Lattice_node**)NULL;
  lat_arrange_cc(lnodes);
  
  // print the header if required
  //
  fprintf(fp_lat_a, "VERSION=1.0\n");
  
  // print the utterance id if available
  //
  if (utterance_d != (char_1*)NULL) {
    fprintf(fp_lat_a, "UTTERANCE=%s\n", utterance_d);
  }

  // print the language Train_Model scale factor and the Train_Word insertion
  // penalty
  //
  fprintf(fp_lat_a, "lmscale=%.2f\n", lm_scale_d);
  fprintf(fp_lat_a, "wdpenalty=%.2f\n", word_penalty_d);

  // write the language Train_Model and acoustic Train_Model used
  //
  if (lang_model_d != (char_1*)NULL) {
    fprintf(fp_lat_a, "vocab=%s\n", lang_model_d);
  }
  if (model_set_d != (char_1*)NULL) {
    fprintf(fp_lat_a, "hmms=%s\n", model_set_d);
  }

  // print the number of nodes and arcs in the Train_Lattice
  //
  fprintf(fp_lat_a, "N=%-8ld  L=%-8ld\n", num_nodes_d, num_arcs_d);
  
  // print out the nodes information
  //
  float_4 frame_idx = (float_4)0; 
  for (int_4 i = 0; i < num_nodes_d; i++) {
    frame_idx = lnodes[i]->get_frame_index_cc() * TRAIN_LATTICE_FRAME_DURATION;
    fprintf(fp_lat_a, "I=%-8ld t=%-.2f\n", i, frame_idx);
  }

  // print out the arcs information
  // 
  int_4 count = (int_4)0;
  int_4 arc_count = (int_4)0;
  int_4 num_arcs_out = (int_4)0;
  float_8* lm_scores = (float_8*)NULL;
  float_8* ac_scores = (float_8*)NULL;

  // loop over all the nodes
  //
  for (int_4 i = 0; i < num_nodes_d; i++) {

    // set the start node for this arc
    //
    start_latn = lnodes[i];

    // get the next nodes list
    //
    nodes_list = start_latn->get_next_nodes_cc();
    
    // if this is not the last node in the Train_Lattice
    //
    if (nodes_list != (Train_Link_list*)NULL) {

      // get the start node information
      //
      num_arcs_out = start_latn->get_num_arcs_out_cc();
      lm_scores = start_latn->get_lm_scores_cc();
      ac_scores = start_latn->get_ac_scores_cc();
      
      // loop over all the next nodes
      //
      count = (int_4)0;
      for (Train_Link_node* lnd = nodes_list->get_head_cc();
	   lnd != (Train_Link_node*)NULL; lnd = lnd->get_next_cc()) {
	
	// get the end Train_Lattice node for each arc
	//
	end_latn = (Train_Lattice_node*)(lnd->get_item_cc());

	// print the arc information and update the arc count
	//
	fprintf(fp_lat_a, "J=%-8ld ", arc_count++);
	fprintf(fp_lat_a, "S=%-8ld ", i);
	fprintf(fp_lat_a, "E=%-8ld ", end_latn->get_node_index_cc());
	fprintf(fp_lat_a, "W=%-16s ", end_latn->get_word_cc()->get_name_cc());
	fprintf(fp_lat_a, "v=%-2ld ", end_latn->get_pron_var_cc());
	fprintf(fp_lat_a, "a=%-10.2f ", ac_scores[count]);
	fprintf(fp_lat_a, "l=%-3.3f\n", lm_scores[count] / lm_scale_d);

	// increment count
	//
	count++;
      }

      // check count
      //
      if (count != num_arcs_out) {
	error_handler_cc((char_1*)"Train_Lattice_write_cc",
			 (char_1*)"Mismatch in number of outgoing arcs.");
      }
      
    } // end if nodes list is not null
  } // end for i loop

  // free memory
  //
  for (int_4 i = 0; i < num_nodes_d; i++) {
    lnodes[i] = (Train_Lattice_node*)NULL;
  }
  delete [] lnodes;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
