// file: dec_lmahead_0.cc
//
 
// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: get_lmahead_cc
//
// arguments:
//  Lex_node* lex: (input) lexical node for the current trace
//  History* hist: (input) history node
//  
// return: a float_4 with the lm look-ahead score
//
// this method computes the lm look-ahead score given the current
// history and the next word
//
float_4 Decoder::get_lmahead_cc(Lex_node* lex_a, History* hist_a) {
  
  // dummy variables
  //
  float_4 lmscore = DEC_DEFAULT_SCORE;
  float_4 score = DEC_DEFAULT_SCORE; 
  
  // if this is a lattice-related mode
  //
  if ((function_mode_d == DEC_LATTICE_RESCORE_FUNCTION) ||
      (function_mode_d == DEC_LATTICE_LATTICE_FUNCTION) ||
      (function_mode_d == DEC_FORCE_ALIGN_FUNCTION)) {
    
    // get the lm score for this word
    //
    lmscore = lex_a->get_score_cc();
    
    // exit gracefully
    //
    return lmscore;
  }

  // if this a ngram decoding mode, but uses dynamic networks
  //
  if (((function_mode_d == DEC_NGRAM_DECODE_FUNCTION) ||
       (function_mode_d == DEC_LATTICE_GENERATE_FUNCTION)) &&
      (lex_a->get_type_cc() == LXN_WORDGRAPH)) {

    // get the lm score for this word
    //
    lmscore = lex_a->get_score_cc();
    
    // exit gracefully
    //
    return lmscore;
  }
  
  // define ngram mode specific variables
  //
  int_4 wdcount = (int_4)0;
  Word** histlist = (Word**)NULL;
  Word** wordlist = new Word*[ngram_order_d];
  Word* curword = (Word*)NULL;
    
  // list of words that end at this point
  //
  Link_list* wrd_list = lex_a->get_words_cc();

  // list of old history words
  //
  void_p* histwords = hist_a->get_histwords_cc();
  
  // find the nodes corresponding to the words that end here
  //
  for (Link_node* lln = wrd_list->get_head_cc();
       lln != (Link_node*)NULL; lln = lln->get_next_cc()) {

    // word list
    //
    wdcount = (int_4)0;
      
    // if this is an ngram-related node
    //
    if ((function_mode_d == DEC_NGRAM_DECODE_FUNCTION) ||
	(function_mode_d == DEC_LATTICE_GENERATE_FUNCTION)) {
      
      // get the current word and put it in the word list
      //
      Ngram_node* ngnode = (Ngram_node*)(lln->get_item_cc());
      curword = ngnode->get_word_cc();
      wordlist[ngram_order_d - 1] = curword;
      wdcount++;

      if (histwords != (void_p*)NULL && ngram_order_d >= 2) {
	curword = ((Ngram_node*)histwords[0])->get_word_cc();
	
	// make sure this is not the dummy start node
	//
	if (curword != (Word*)NULL) {
	  wordlist[ngram_order_d - 1 - wdcount] = curword;
	  wdcount++;
	}
      }
    }
    
    // otherwise this is lattice rescoring with ngram lm
    //
    else if (function_mode_d == DEC_LATTICE_VERIFY_FUNCTION) {
      
      // get the current word
      //
      Lattice_node* latnode = (Lattice_node*)(lln->get_item_cc());
      curword = latnode->get_word_cc();
      wordlist[ngram_order_d - 1] = curword;
      wdcount++;
      if (histwords != (void_p*)NULL && ngram_order_d >= 2) {

	curword = ((Lattice_node*)histwords[0])->get_word_cc();
	
	// make sure this is not the dummy lat start node
	//
	if (curword != (Word*)NULL) {
	  wordlist[ngram_order_d - 1 - wdcount] = curword;
	  wdcount++;
	}
      }
    }
    
    // find more previous history words if needed
    //
    if ( ngram_order_d >= 3 && histwords != (void_p*)NULL
	 && curword != (Word*)NULL) {
      while (wdcount < ngram_order_d &&
	     histwords[wdcount-1] != (void_p)NULL) {
	
	// add this word
	//
	wordlist[ngram_order_d - 1 - wdcount] = (Word*)histwords[wdcount-1];
	wdcount++;
      }
    }
    
    // get the lm score for this ngram
    //
    histlist = wordlist + ngram_order_d - wdcount;
    score = ngram_d->get_score_cc(wdcount, histlist);
    if (lmscore < score) {
      lmscore = score;
    }	
    
    /*--
      printf("Frame %ld : dcount %ld : Lmscore %.6f",
      frame_d, wdcount, score);
      for (int_4 q = 0; q < wdcount; q++) {
      printf (" %s", histlist[q]->get_name_cc());
      }
      printf ("\n");
      --*/

  } // end loop over all words covered by this lex node

  // free memory
  //
  delete [] wordlist;
  wordlist = (Word**)NULL; 
  
  // exit gracefully
  //
  return lmscore;
}
