// file: dec_clean_1.cc
//

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

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: reset_cc
//
// arguments: none
//
// return: logical_1 indicating status
//
// this method resets and re-allocates if necessary the decoder
// contents that need to be cleaned up before decoding a new utterance
//
logical_1 Decoder::reset_cc() {

  // dummy variables
  //
  int_4 index = (int_4)0;
  void_p startnode = (void_p)NULL;
  Hash_cell* icell = (Hash_cell*)NULL;
  Word* word_null = (Word*)NULL;
  Lattice_node* latnode = (Lattice_node*)NULL;
  Lex_tree* tree = (Lex_tree*)NULL;
  Lex_node* lxn = (Lex_node*)NULL;
  History* hist = (History*)NULL;
  void_p* hist_word = (void_p*)NULL;
  Instance* inst = (Instance*)NULL;
  Trace* tr = (Trace*)NULL;

  // reset the memory manager if necessary
  //
  if (restructure_memory_d == ISIP_TRUE) {
    manager_d->reorder_blocks_cc();
  }
  
  // reset frame index
  //
  frame_d = (int_4)0;
  
  // initialize the history list
  //
  history_list_d = new Link_list();
  
  // allocate a new instance table
  //
  inst_table_d = new Hash_table((int_4)ISIP_2EXP16, HASH_TABLE_LONG_DRIVEN);
  
  // initialize the active instance list
  //
  inst_count_d = (int_4)0;
  inst_list_d = new Link_list();
  
  // initialize the word-level lists
  //
  for (int_4 i = 0; i < num_words_d; i++) {
    active_words_d[i] = (int_4)-1;
    word_trlist_d[i] = (Link_list*)NULL;
    word_scores_d[i] = DEC_DEFAULT_SCORE;
  }
  
  // initialize the model level lists
  //
  for (int_4 i = 0; i < num_cd_d; i++) {
    active_models_d[i] = (int_4)-1;
    model_trlist_d[i] = (Link_list*)NULL;
    cd_models_d[i]->set_active_cc(ISIP_FALSE);
  }
  
  // initialize the nbest array
  //
  for (int_4 i = 0; i < num_nbest_d; i++) {
    nbest_d[i] = (Trace*)NULL;
  }
    
  // reset states in the models
  //
  for (int_4 i = 0; i < num_states_d; i++) {
    states_d[i]->set_frame_cc(frame_d);
    states_d[i]->set_score_cc((float_4)0);
  }
    
  // initialize counts, beams and scores
  //
  frame_d = (int_4)0;
  num_active_models_d = (int_4)0;
  num_active_words_d = (int_4)0;
  num_hyps_d = (int_4)0;
  mapmi_thresh_d = DEC_DEFAULT_SCORE;
  wordend_thresh_d = DEC_DEFAULT_SCORE;
  
  for (int_4 i = 0; i < num_levels_d; i++) {
    num_traces_total_d[i] = (int_4)0;
    num_traces_gen_d[i] = (int_4)0;
    num_traces_del_d[i] = (int_4)0;
    total_gen_d[i] = (int_4)0;
    total_del_d[i] = (int_4)0;

    // note that this is not set to default instance score to allow for
    // instance to be pruned even when beams are not specified by the
    // user or are set to zero
    //
    beam_thresh_d[i] = INSTANCE_ACTIVE_SCORE;
    max_score_d[i] = INSTANCE_ACTIVE_SCORE;
  }    
  
  // create a sentence start trace
  //
  tr = manager_d->new_trace_cc();    
  tr->set_level_cc(DEC_WORD_LEVEL);
  tr->set_score_cc((float_4)0);
  
  // initialize the active word list with the null word
  //
  word_null = (Word*)((lexicon_d->hash_lookup_cc(WRD_NULL))->get_item_cc());
  index = word_null->get_index_cc();
  active_words_d[num_active_words_d++] = index;
  
  // insert the start trace in the correct list
  //
  word_trlist_d[index] = new Link_list();
  word_trlist_d[index]->insert_cc(tr);
  num_traces_gen_d[DEC_WORD_LEVEL]++;
  
  // if this function mode requires lattice input
  //
  if ((function_mode_d == DEC_LATTICE_RESCORE_FUNCTION) ||
      (function_mode_d == DEC_LATTICE_VERIFY_FUNCTION)  ||
      (function_mode_d == DEC_LATTICE_LATTICE_FUNCTION) ||
      (function_mode_d == DEC_FORCE_ALIGN_FUNCTION)) {
    
    // initialize list to store the active lexical trees
    //
    lextree_list_d = new Link_list();

    // set the word information for the start trace
    //
    latnode = lattice_d->get_start_node_cc();
    startnode = latnode;

    hist_word = next_histwords_cc((void_p*)NULL, (void_p)startnode);
    
    // set the history to the start node
    //
    hist = manager_d->new_hist_cc();
    hist->init_cc(hist_word, DEC_WORD_LEVEL, sil_model_d, (int_4)0,
		  frame_d, (float_4)0);
    hist->set_type_cc(HISTORY_WORDGRAPH);
    tr->set_hist_cc(hist);
    history_list_d->insert_cc((void_p)hist);
    
    // set the lexical information for the start trace
    // create a new tree if one doesn't exist
    //
    tree = latnode->get_lex_tree_cc();
    if (tree == (Lex_tree*)NULL) {
      
      // build a start tree with the appropriate LM look-ahead
      //
      tree = new Lex_tree(startnode);
      
      // set the appropriate params in the lattice node
      //
      latnode->set_lex_tree_cc(tree);
      
      // insert it in the list of active trees
      //
      lextree_list_d->insert_cc(tree);
    }
  } // end if lattice mode
  
  // otherwise if this is ngram lm decoding mode
  //
  else if ((function_mode_d == DEC_NGRAM_DECODE_FUNCTION) ||
	   (function_mode_d == DEC_LATTICE_GENERATE_FUNCTION)) {

    // set the history to the start node
    //
    hist = manager_d->new_hist_cc();

    hist_word = next_histwords_cc((void_p*)NULL, (void_p)startnode);
    
    hist->init_cc(hist_word, DEC_WORD_LEVEL, sil_model_d, (int_4)0,
		  frame_d, (float_4)0);
    hist->set_type_cc(HISTORY_NGRAM);
    tr->set_hist_cc(hist);
    history_list_d->insert_cc((void_p)hist);
    
    // set the lexical tree
    //
    tree = (Lex_tree*)(lextree_list_d->get_head_cc()->get_item_cc());
    
  } // end if ngram mode

  // create a new instance for this trace
  //
  lxn = tree->get_head_cc();
  inst = manager_d->new_instance_cc();
  inst->set_params_cc(lxn, sil_model_d);
  
  // put it in the instance table
  //
  index = 0;
  int_4 hist_len = History::get_hist_len_cc();

  int_4* hash_key = new int_4[hist_len + 2];
  memset(hash_key, 0, (hist_len+2) * sizeof(int_4));
  hash_key[0] = sil_model_d;
  hash_key[1] = (int_4)lxn;

  if (hist_word != (void_p*)NULL) {
    while (index < hist_len && hist_word[index] != (void_p)NULL) {
      hash_key[index + 2] = (int_4)hist_word[index];
      index++;
    }
  }
  
  icell = manager_d->new_hash_cc();
  icell->set_cc(hash_key, hist_len + 2, (void_p)inst);
  inst_table_d->hash_insert_cc(icell);

  // delete the hash_key
  //
  delete [] hash_key;
  
  // insert the instance in the active instance list
  //
  inst->set_frame_cc(frame_d);
  inst->set_score_cc(INSTANCE_ACTIVE_SCORE);
  inst_list_d->insert_cc((void_p)inst);
  inst_count_d++;
  
  // set the instance in the trace
  //
  tr->set_inst_cc(inst);
  
  // update counts
  //
  for (int_4 i = 0; i < num_levels_d; i++) {
    total_gen_d[i] += num_traces_gen_d[i];
    total_del_d[i] += num_traces_del_d[i];
    num_traces_total_d[i] += (num_traces_gen_d[i] - num_traces_del_d[i]);
  }
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
