// file: dec_lat_6.cc
//

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: lattice_to_nbest_cc
//
// arguments:
//  FILE* flat: (input) input lattice file
//  FILE* fout: (input) output file for nbest hypothesis
//  int_4 max_paths: (input) maximum number of partial paths per frame
//  float_8 beam: (input) beam width for pruning partial paths 
//
// return: logical_1 indicating status
//
// this method generates an nbest list from a lattice using a stack decoder
// like structure, similar to the one used in Sphinx 3 (ref. Ravishankar's
// 1997 darpa hub-4 workshop presentation)
//
//
logical_1 Decoder::lattice_to_nbest_cc(FILE* flat_a, FILE* fout_a,
				       int_4 max_paths_a, float_8 beam_a) {

   // dummy variables
  //
  Lattice_node* ltn = (Lattice_node*)NULL;
  Hash_cell* next = (Hash_cell*)NULL;
  int_4 frame_index = (int_4)0;
  int_4 max_frame = (int_4)-1;
  
  // initialize lattice if not done so
  //
  if (lattice_d == (Lattice*)NULL) {
    lattice_d = new Lattice();
  }
  else {
    delete lattice_d;
    lattice_d = new Lattice();
  }
  
  // read the lattice from file
  //
  lattice_d->read_lattice_cc(flat_a, lexicon_d);

  // find the length of the utterance by searching all lattice nodes
  // for the maximum time index
  //
  Hash_table* htable = lattice_d->get_lnodes_cc();
  Hash_cell** hcells = htable->get_cells_cc();
  int_4 hash_size = htable->get_size_cc();

  // loop through all the lattice nodes stored in the hash table
  //
  for (int_4 k = 0; k < hash_size; k++) {
    for (Hash_cell* lcell = hcells[k]; lcell != (Hash_cell*)NULL;
	 lcell = next) {
      next = lcell->get_next_cc();
      ltn = (Lattice_node*)(lcell->get_item_cc());
      frame_index =  ltn->get_frame_index_cc();
      
      // get maximum frame index
      //
      if (max_frame < frame_index) {
	max_frame = frame_index;
      }
    }
  }

  // initialize max_frame number of path lists (assuming a zero based frame
  // indexing scheme)
  //
  Path_list** plist = new Path_list*[max_frame+1];
  for (int_4 i = 0; i <= max_frame; i++) {
    plist[i] = new Path_list;
  }

  // get the start node and populate the path list for the zero'th frame
  //
  Lattice_node* start_node = lattice_d->get_start_node_cc();
  Nbest_node* nnode = new Nbest_node(start_node, (Nbest_node*)NULL,
				     (float_8)0);
  plist[0]->add_path_cc(nnode);

  // process path lists for each frame except the last frame since paths
  // terminate there
  //
  for (int_4 i = 0; i < max_frame; i++) {

    // need to grow the list only if partial paths exist
    //
    if (plist[i]->get_num_paths_cc() != 0) {
      plist[i]->set_frame_ind_cc(i);
      plist[i]->prune_cc(beam_a, max_paths_a);
      plist[i]->grow_paths_cc(plist, lattice_d->get_lm_scale_cc(),
			      lattice_d->get_word_penalty_cc(),
			      max_paths_a, beam_a);
    }
  }
    
  // write the nbest hypothesis
  //
  write_nbest_cc(fout_a, plist[max_frame]);
		 
  // clean up
  //
  for (int_4 i = 0; i <= max_frame; i++) {
    delete plist[i];
  }
  delete [] plist;

  // exit gracefully
  //
  return ISIP_TRUE;
}
