// file: dec_inst_0.cc
//
 
// system include files
//
#include <string.h>

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"

static int_4* hash_key = (int_4*)NULL;
static int_4 hash_key_length = 0;

// method: get_instance_cc
//
// arguments:
//  Instance*& inst: (output) the instance for this trace
//  History* hist: (input) the history node for this trace
//  Lex_node* lexch: (input) the next lexical node
//  int_4 phn: (input) the cd model index
//  
// return: a logical_1 indicating status
//
// this method procures the instance based on the given data, and
// creates a new one if one does not exist; in which case it also
// updates the instance count and calculates the lm lookahead score
//
logical_1 Decoder::get_instance_cc(Instance*& inst_a, History* hist_a,
				   Lex_node* lex_a, int_4 phn_a) {

  // dummy variables
  //
  Hash_cell* instcell = (Hash_cell*)NULL;
  Hash_cell* newcell = (Hash_cell*)NULL;
  float_4 lmscore = (float_4)0;
  int_4 index = 0;
  
  // history word
  //
  int_4 hist_len = History::get_hist_len_cc();
  void_p* histwords = hist_a->get_histwords_cc();

  if (hash_key_length < (hist_len + 2)) {
    hash_key_length = hist_len + 2;
    if (hash_key != (int_4*)NULL) {
      delete [] hash_key;
    }
    hash_key = new int_4[hash_key_length];
    memset(hash_key, (int_4)0, hash_key_length * sizeof(int_4));   
  }
  
  // see if this instance is already active
  //
  hash_key[0] = phn_a;
  hash_key[1] = (int_4)lex_a;
  
  // clear hash key at each function call
  memset(hash_key+2, (int_4)0, hist_len * sizeof(int_4));
  
  if (histwords != (void_p*)NULL) {
    while (index < hist_len && histwords[index] != (void_p)NULL) {
      hash_key[index + 2] = (int_4)histwords[index];
      index++;
    }
  }
  else {
    while (index < hist_len) {
      hash_key[index + 2] = 0;
      index++;
    }
  }
  
  instcell = inst_table_d->hash_lookup_cc(hash_key, hist_len + 2);
  
  // if this instance didn't exist previously, create one and put it
  // in the table
  //
  if (instcell == (Hash_cell*)NULL) {
    
    // create a new instance
    //
    inst_a = manager_d->new_instance_cc();
    inst_a->set_params_cc(lex_a, phn_a);
    
    // put the new instance in the hash table and the instance list
    //
    newcell = manager_d->new_hash_cc();
    newcell->set_cc(hash_key, hist_len + 2, (void_p)inst_a);
    inst_table_d->hash_insert_cc(newcell);
  }
  
  // else get the instance from the instance table
  //
  else {
    inst_a = (Instance*)(instcell->get_item_cc());
  }
  
  // set the instance lm score and scale the lm score
  //
  if (inst_a->get_lmscore_cc() == INSTANCE_DEFAULT_SCORE) {
    lmscore = get_lmahead_cc(lex_a, hist_a);
    inst_a->set_lmscore_cc(lmscore);
  }

  // check to see if this is an active instance, if not insert into
  // list
  //
  if (inst_a->get_score_cc() == INSTANCE_DEFAULT_SCORE) {
    inst_a->set_score_cc(INSTANCE_ACTIVE_SCORE);
    inst_list_d->insert_cc((void_p)inst_a);
    inst_count_d++;
  }

  // exit gracefully
  //
  return ISIP_TRUE;
}
