// file: dec_lat_5.cc
//
 
// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"

// method: add_arc_cc
//
// arguments:
//  int_4 level : (input) level at which the current word is in ngram
//  Word** words: (input) the array of words
//  int_4 wdcount : (input) number of words in array
//  float_4 score : (input) the path score for word node
//  History* hist_a : (input) the previous history node
//  Lattice_node* latnode : (input) current next lattice node
//  Lattice_node* latn : (input) current lattice node
//  int_4& num_arcs : (output) number of arcs in lattice
//
// return: a logical_1 indicating status
//
// this method recursively backtracks over history nodes on a path to
// compute the correct ngram LM score, and adds the lattice node arcs
// accordingly
//
logical_1 Decoder::add_arcs_cc (int_4 level_a, Word** words_a,
				int_4 wdcount_a, float_4 score_a,
				History* hist_a, Lattice_node* latnode_a,
				Lattice_node* latn_a, int_4& num_arcs_a) {
  
  // first generate the ngram if necessary
  //
  if (level_a < ngram_order_d) {
    
    // increment level
    //
    level_a++;
    
    // get the previous histories list
    //
    void_p wnode = (void_p)NULL;
    Word* curwd = (Word*)NULL;
    History* hist = (History*)NULL;
    Link_list* histlist = hist_a->get_prev_list_cc();
    if (histlist != (Link_list*)NULL) {
      
      // loop over all words here
      //
      for (Link_node* lnd = histlist->get_head_cc();
	   lnd != (Link_node*)NULL; lnd = lnd->get_next_cc()) {
	
	// get the history node here
	//
	hist = (History*)(lnd->get_item_cc());
	wnode = hist->get_histwords_cc((int_4)0);
	
	// add this word
	//
	if (wnode != (void_p)NULL) {
	  
	  // get the word
	  //
	  if (hist->get_type_cc() == HISTORY_NGRAM) {
	    curwd = ((Ngram_node*)wnode)->get_word_cc();
	  }
	  else {
	    curwd = ((Lattice_node*)wnode)->get_word_cc();
	  }
	  
	  // add it to the list
	  //
	  if (hist->get_level_cc() == HISTORY_WORD_LEVEL &&
	      curwd != (Word*)NULL) {
	    words_a[ngram_order_d - 1 - wdcount_a] = curwd;
	    
	    // pass on for getting the lm score
	    //
	    add_arcs_cc (level_a, words_a, wdcount_a + 1, score_a,
			 hist, latnode_a, latn_a, num_arcs_a);
	  } // end if
	} // end if wnode is not null

	// otherwise add the arc right here
	//
	else {
	  add_arcs_cc (level_a, words_a, wdcount_a, score_a,
		       hist_a, latnode_a, latn_a, num_arcs_a);
	}
      } // end for loop over all hist words
    } // end if hist list is not null
    
    // otherwise add the arc right here
    //
    else {
      add_arcs_cc (level_a, words_a, wdcount_a, score_a,
		   hist_a, latnode_a, latn_a, num_arcs_a);
    }
  } // end if level is not ngram_order_d

  // otherwise get the lmscore if the ngram is complete
  //
  else {
    
    // get the lm score for this ngram
    //
    Word** ngwords = words_a + ngram_order_d - wdcount_a;
    float_4 lmscore = ngram_d->get_score_cc(wdcount_a, ngwords);
    
    // get the acoustic score
    //
    float_4 acscore = score_a - (lmscore * lmscale_d + wdpenalty_d);
    
    // set up the arc connections
    //
    latn_a->add_next_node_cc(latnode_a);
    num_arcs_a++;
    
    // add the language model and acoustic scores
    //
    latn_a->add_lm_score_cc(lmscore);
    latn_a->add_ac_score_cc(acscore);
    
  }
    
  // exit gracefully
  //
  return ISIP_TRUE;
}
