// file: dec_project_5.cc
//
 
// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
static int_4* trans_states = (int_4*)NULL;
static float_4* trans_scores = (float_4*)NULL;
static int_4 trans_states_size = 0;

// method: grow_trace_cc
//
// arguments:
//  Trace* trace: (input) the trace to be projected
//  Instance* inst: (input) the instance for the new trace
//  int_4 phone: (input) the real cd model index
//  Lex_node* lexnext: (input) the lex node with the new ci phone
//  
// return: a logical_1 indicating status
//
// this method loops over all word and model level traces, and
// projects traces into the entry states of new models
//
logical_1 Decoder::grow_trace_cc(Trace* trace_a, Instance* inst_a,
				 int_4 phone_a, Lex_node* lexnext_a) {

  // dummy variables
  //
  int_4 num_trans = (int_4)0;
  float_4 lmscore = (float_4)0;
  logical_1 flag = ISIP_FALSE;
  
  // model params
  //
  int_4 num_st = (int_4)0;
  Model* model = (Model*)NULL;  

  // new trace
  //
  Trace* new_trace = (Trace*)NULL;

  // history parameters
  //
  History* hist = trace_a->get_hist_cc();
  History* new_hist = (History*)NULL;

  // get the lm score
  //
  lmscore = inst_a->get_lmscore_cc();
  lmscore *= lmscale_d;

  // get the triphone model params
  //
  model = cd_models_d[phone_a]->get_model_cc();
  num_st = model->get_num_states_cc();
  
  // find all possible start states for this phone
  //
  model->get_next_states_cc((int_4)0, num_trans, trans_states,
			    trans_scores, trans_states_size);

  // get the current trace score
  //
  float_4 trscore = trace_a->get_score_cc();
  float_4 new_score = (float_4)0;
  
  // loop over all of the possible next states and
  // pass traces to each
  //
  for (int_4 kk = 0; kk < num_trans; kk++) {
    
    // check for phones in their stop state
    //
    if (trans_states[kk] < num_st - (int_4)1) {
      
      // create a new trace with the transitioned state
      //
      new_trace = manager_d->new_trace_cc();
      new_trace->project_trace_cc(trace_a);
      new_trace->set_state_ind_cc(trans_states[kk]);
      new_trace->set_phone_ind_cc(phone_a);
      
      // the new trace score
      //
      new_score = trscore + trans_scores[kk] + lmscore;
      new_trace->set_score_cc(new_score);

      // update instance score only if this is an old instance;
      // otherwise, keep it from being pruned in instance pruning
      // so that the new traces are allowed to propagate
      //
      if (inst_a->get_score_cc() != INSTANCE_ACTIVE_SCORE) {
	inst_a->compare_score_cc(new_score);
      }
      
      // set the new instance
      //
      new_trace->set_inst_cc(inst_a);
      
      // update the new lexical node
      //
      new_trace->set_lex_next_cc(lexnext_a);

      // set the level to state
      //
      new_trace->set_level_cc(DEC_STATE_LEVEL);

      // set the history parameters
      //
      new_trace->set_max_hist_cc(DEC_STATE_BACKPTR);

      // create a new history node if this is state-level alignment
      //
      if (align_mode_d == DEC_STATE_ALIGN_MODE) {
	
	// history pointers
	//
	new_hist = manager_d->new_hist_cc();

	// copy the histwords
	//
	void_p* prev_words = hist->get_histwords_cc();
	
	int_4 hist_len = History::get_hist_len_cc();
	void_p* newhist_words = new void_p[hist_len];
	
	for (int_4 i = 0; i<hist_len; i++) {
	  newhist_words[i] = prev_words[i];
	}
	
	// set parameters in the new history
	//
	new_hist->init_cc(newhist_words, DEC_STATE_LEVEL, phone_a,
			  trans_states[kk], hist->get_frame_ind_cc(),
			  new_score);
	history_list_d->insert_cc((void_p)new_hist);
                  
	// set the correct history node
	//
	new_trace->set_hist_cc(new_hist);
	new_trace->add_path_cc(hist, new_score);

	// set alignment flag
	//
	flag = ISIP_TRUE;
      }
      
      // insert this in the corresponding state list
      //
      if (inst_a->insert_trace_cc(new_trace, trans_states[kk], flag,
				  max_score_d[DEC_STATE_LEVEL])
	  == ISIP_TRUE) {
	num_traces_gen_d[DEC_STATE_LEVEL]++;
      }
    }
  } // end loop over all transitions
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
