// file: dec_lat_2.cc
//

// system include files
//
#include <string.h>

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: build_lattice_cc
//
// arguments:
//  FILE* fp: (input) file pointer to write the lattice to
//
// return: a logical_1 indicating status
//
// this method backtracks over all sentence-end hypotheses and puts
// all paths into a lattice or word graph structure and writes it to
// the file
//
logical_1 Decoder::build_lattice_cc(FILE* fp_a) {

  // make sure that this is lattice generation mode
  //
  if ((function_mode_d != DEC_LATTICE_GENERATE_FUNCTION) &&
      (function_mode_d != DEC_LATTICE_LATTICE_FUNCTION)) {

    // exit gracefully
    //
    return ISIP_TRUE;
  }
    
  // dummy variables
  //
  float_4 score = (float_4)0;
  int_4 num_nodes = (int_4)0; 
  int_4 num_arcs = (int_4)0;
  History* hist = (History*)NULL;
  Lattice_node* latn = (Lattice_node*)NULL;
  Lattice* outlat = (Lattice*)NULL;
  
  // create a new lattice
  //
  outlat = new Lattice();

  // set the lattice properties
  //
  outlat->set_lm_scale_cc(lmscale_d);
  outlat->set_word_penalty_cc(wdpenalty_d);

  // set up a hash table to hold the lattice nodes
  //
  Hash_table* lathash = new Hash_table(num_nodes);
  Hash_cell* hcell = manager_d->new_hash_cc();
  
  // create the lattice start node
  //
  latn = manager_d->new_lat_cc();
  latn->set_frame_index_cc((int_4)0);
  latn->set_node_index_cc(num_nodes++);

  // insert the new node in the hash table
  //
  static char_1 str[LATTICE_KEYSTR_LENGTH];
  strcpy((char*)str, "");
  sprintf((char*)str, "%p", (Trace*)NULL);
  hcell->set_cc(str, latn);
  lathash->hash_insert_cc(hcell);

  // set the lattice nodes in the new lattice
  //
  outlat->set_lnodes_cc(lathash);
  outlat->set_start_node_cc(latn);
  
  // loop over all sentence end traces and fill up the lattice
  //
  for (int_4 i = 0; i < num_hyps_d; i++) {

    // get the path history score
    //
    hist = nbest_d[i]->get_hist_cc();
    score = hist->get_score_cc();

    // for each sentence end back-track over all paths merging here
    // and construct lattice
    //
    if (function_mode_d == DEC_LATTICE_GENERATE_FUNCTION) {
      ngram_to_lattice_cc(num_nodes, num_arcs, lathash, hist,
			  (Lattice_node*)NULL, (void_p)NULL, score);
    }
    else if (function_mode_d == DEC_LATTICE_LATTICE_FUNCTION) {
      lattice_to_lattice_cc(num_nodes, num_arcs, lathash, hist,
			    (Lattice_node*)NULL, (Lattice_node*)NULL,
			    score);
    }
  } // end for i
  
  // set the correct numbers of nodes and arcs
  // 
  outlat->set_num_nodes_cc(num_nodes);
  outlat->set_num_arcs_cc(num_arcs);
  
  // reorder the lattice
  //
  outlat->index_nodes_cc();

  // compact and write the lattice
  //
  if (compact_lattice_d) {
    Lattice* newlat = (Lattice*)NULL;
    printf("write compacted lattice!\n");
    outlat->reduce_lattice_cc(newlat);

    // write this to the output lattice file
    //
    newlat->write_lattice_cc(fp_a, ISIP_FALSE, ISIP_FALSE, ISIP_FALSE);

    // free memory
    //
    delete outlat;
    delete newlat;
    outlat = (Lattice*)NULL;
    newlat = (Lattice*)NULL;
  }

  // write the full lattice
  //
  else {

    // write this to the output lattice file
    //
    outlat->write_lattice_cc(fp_a, ISIP_FALSE, ISIP_FALSE, ISIP_FALSE);
    
    // free memory
    //
    delete outlat;
    outlat = (Lattice*)NULL;
  }
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
