// file: lat_wer_0.cc
//

// isip include files
//
#include "lattice.h"
#include "lattice_constants.h"

// method: error_rate_cc
//
// arguments:
//  char_1*& utterance: (output) the best matching utterance
//  int_4& nref: (output) number of reference words
//  int_4& corr: (output) number of correct words
//  int_4& subs: (output) number of substitutions
//  int_4& dels: (output) number of deletions
//  int_4& ins: (output) number of insertions
//  Hash_table* lexicon: (input) lexicon for this task
//
// return: a logical_1 indicating status
//
// this method dynamically aligns all the possible strings generated
// by this lattice with the reference utterance transcription and
// finds the best match, along with the number of substitution,
// deletion and insertion errors
//
logical_1 Lattice::error_rate_cc(char_1*& utterance_a, int_4& nref_a,
				 int_4& corr_a, int_4& subs_a, int_4& dels_a,
				 int_4& ins_a, Hash_table* lexicon_a) {

  // memory manager
  //
  Memory_manager* manager = Link_list::get_manager_cc();

  if ((lexicon_a->hash_lookup_cc(WRD_NULL)) != (Hash_cell*)NULL) {
    null_word_d =
      (Word*)((lexicon_a->hash_lookup_cc(WRD_NULL))->get_item_cc());
  }
  
  
  // best path of all
  //
  Lattice_path* best_path = (Lattice_path*)NULL;
  
  // break the reference transcription into a word list of indices
  //
  nref_a = (int_4)0;
  Word** ref_words = get_ref_words_cc(nref_a, lexicon_a);

  // create a link list to hold all older path nodes
  //
  Link_list* holder_list = new Link_list();
  
  // create a start path node with sentence start
  //
  int_4 idx = start_node_d->get_node_index_cc();
  Lattice_path* stpath = manager->new_lpath_cc();
  stpath->set_curr_cc(start_node_d);

  // check if there exists a perfect match for the reference first
  // only if there is no perfect match grow paths
  //
  if (correct_path_cc(stpath, nref_a, ref_words, holder_list,
		      best_path) == ISIP_FALSE) {
  
    // free the holder list
    //
    free_list_cc(holder_list);
    delete holder_list;
    holder_list = (Link_list*)NULL;

    // create a new holder link list to hold all older path nodes
    //
    holder_list = new Link_list();
  
    // lattice path lists for each lattice node
    //
    int_4 num_active = (int_4)0;
    Link_list** path_list = new Link_list*[num_nodes_d];
    Link_node** markers = new Link_node*[num_nodes_d];
    for (int_4 i = 0; i < num_nodes_d; i++) {
      path_list[i] = (Link_list*)NULL;
      markers[i] = (Link_node*)NULL;
    }

    // add the start path to the correct list
    //
    stpath = manager->new_lpath_cc();
    stpath->set_curr_cc(start_node_d);
    add_path_cc(path_list[idx], markers[idx], stpath);
    num_active++;
    
    // as long as there are destination nodes possible dynamically
    // grow paths
    //
    while (num_active > (int_4)0) {
      
      // grow paths and compare with the reference
      //
      num_active = grow_paths_cc(nref_a, ref_words, holder_list, path_list,
				 markers, best_path);
      
    } // end while loop

    // free memory in path link lists
    //
    for (int_4 i = 0; i < num_nodes_d; i++) {
      free_list_cc(path_list[i]);
      delete path_list[i];
      path_list[i] = (Link_list*)NULL;
    }
    delete [] path_list;
    path_list = (Link_list**)NULL;
    
    // free memory in markers list
    //
    delete [] markers;
    markers = (Link_node**)NULL;
    
  } // end if there is no perfect matching path
  
  // backtrack from the best path to generate best aligned word
  // sequence and output to stdout
  //
  backtrack_cc(best_path, ref_words, nref_a, utterance_a, corr_a,
	       subs_a, dels_a, ins_a);

  // discount sentence start and end from the reference words
  //
  nref_a -= (int_4)2;

  // free memory in the word list
  //
  delete [] ref_words;
  ref_words = (Word**)NULL;
  
  // free memory in path link lists
  //
  free_list_cc(holder_list);
  delete holder_list;
  holder_list = (Link_list*)NULL;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
