// file: lat_wer_7.cc
//

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

// method: correct_subpath_cc
//
// arguments:
//  Lattice_path* stpath: (output) the start path
//  Word** words: (input) list of reference words
//  Lattice_path*& best: (output) the best path at this point
//  int_4 nref: (input) number of reference words
//  int_4 idx: (input) current word index number (default = 0) 
//
// return: a logical_1 to indicate status
//
// this recursive method checks if a subpath exists starting at stpath_a that exactly
// matches the word sequence in words_a.
//
logical_1 Lattice::correct_subpath_cc(Lattice_path* stpath_a, Word** words_a, 
				      Lattice_path*& best_a, int_4 nref_a, 
				      int_4 idx_a) {


  // set the best path porinter to NULL
  //
  best_a = (Lattice_path*)NULL;

  // exit condition. check if this node matches. if not,
  // we can go ahead and exit
  //
  Lattice_node* curr_node = stpath_a->get_curr_cc();
  if (curr_node->get_word_cc() != words_a[idx_a]) {
    return ISIP_FALSE;
  }

  // exit condition: if it does match, and we've reached the last
  // word, we've found a match
  //
  else {
    if (idx_a == nref_a - 1) {
      best_a = stpath_a;
      return ISIP_TRUE;
    }
  }

  // get list of next nodes
  //
  Link_list* next_nodes = curr_node->get_next_nodes_cc();

  // get the starting frame of this node (is actually the frame when 
  // this node ends, but since we're only checking paths emitted from
  // this node, it'll work)
  //
  int_4 start_frame = curr_node->get_frame_index_cc();

  // if there are no following nodes, we can exit
  //
  if (next_nodes == (Link_list*)NULL) {
    return ISIP_FALSE;
  }

  float_4 max_score = 0;

  for (Link_node* lnd = next_nodes->get_head_cc(); 
       lnd != (Link_node*)NULL; lnd = lnd->get_next_cc()) {

    // get this node
    //
    Lattice_node* this_node = (Lattice_node*)lnd->get_item_cc();

    // create new path with this next node. the validity of this next node
    // isn't checked here, but in the next recursive call of this function
    //
    Lattice_path* new_path = new Lattice_path();
    new_path->project_cc(stpath_a, this_node, LATTICE_PATH_CORRECT);

    // create output match path
    //
    Lattice_path* match_path = NULL;

    // make recursive call to this function. idx is incremented to check for the 
    // next word
    //
    if (correct_subpath_cc(new_path, words_a, match_path, nref_a, idx_a+1)) {

      // compute score of this path
      //
      float_4 ac_score = 0;
      float_4 lm_score = 0;
      float_4 path_score = 0;
      int_4 end_frame = match_path->get_curr_cc()->get_frame_index_cc();

      match_path->path_likelihood_cc(lm_scale_d, word_penalty_d, ac_score, lm_score);
      path_score = ac_score/(end_frame-start_frame);

      // if this is a potential path
      //
      if ((path_score > max_score || max_score == 0)) {
	max_score = path_score;

	// delete the current best path
	//
	delete best_a;
	// set the new best path
	//
	best_a = match_path;
      }

      // if this isn't a potential best path
      //
      else {

	// delete the match_path
	//
	delete new_path;
      }      
    }
    else {
      delete new_path;
    }
  }

  if (best_a != NULL) {
    return ISIP_TRUE;
  }

  // exit gracefully
  //
  return ISIP_FALSE;
}
