// file: dec_clean_2.cc
//

// isip include files
//
#include "decoder.h"
#include "decoder_constants.h"
 
// method: clean_cc
//
// arguments: none
//
// return: logical_1 indicating status
//
// this is the method that does clean up of all memory use to process
// an utterance
//
logical_1 Decoder::clean_cc(logical_1 isCommunicator_a) {

  // local variables
  //
  Link_node* nd = (Link_node*)NULL;
  Link_node* pd = (Link_node*)NULL;
  Link_list* trlist = (Link_list*)NULL;
  
  History* hist = (History*)NULL;
  Lex_tree* tree = (Lex_tree*)NULL;
  Trace* tr = (Trace*)NULL;
  int_4* ele = (int_4*)NULL;
  
  // increment the number of utterances decoded
  //
  num_utt_d++;
  
  // free memory in history nodes
  //
  for (nd = history_list_d->get_head_cc(); nd != (Link_node*)NULL; nd = pd) {
    pd = nd->get_next_cc();
    hist = (History*)(nd->get_item_cc());
    manager_d->delete_cc(hist);
    history_list_d->remove_cc(nd);
  }
  delete history_list_d;
  history_list_d = (Link_list*)NULL;
  
  // reset the instance table and remove the instance list
  //
  delete inst_list_d;
  inst_list_d = (Link_list*)NULL;
  clean_instances_cc();
  
  // free lattice-related memory
  //
  if (((function_mode_d == DEC_LATTICE_RESCORE_FUNCTION) &&
       (isCommunicator_a == ISIP_FALSE)) ||
      (function_mode_d == DEC_LATTICE_VERIFY_FUNCTION) ||
      (function_mode_d == DEC_LATTICE_LATTICE_FUNCTION) ||
      (function_mode_d == DEC_FORCE_ALIGN_FUNCTION)) {
    
    // free memory in active lexical tree list
    //
    for (nd = lextree_list_d->get_head_cc(); nd != (Link_node*)NULL;
	 nd = pd) {
      pd = nd->get_next_cc();
      tree = (Lex_tree*)(nd->get_item_cc());
      lextree_list_d->remove_cc(nd);
      if (tree != (Lex_tree*)NULL) {
	delete tree;
      }
    }
    delete lextree_list_d;
    lextree_list_d = (Link_list*)NULL;
    
    // free memory
    //
    delete lattice_d;
    lattice_d = (Lattice*)NULL;
  }
  else if ((function_mode_d == DEC_LATTICE_RESCORE_FUNCTION) &&
	   (isCommunicator_a == ISIP_FALSE)) {
    
    // free memory in active lexical tree list
    //
    for (nd = lextree_list_d->get_head_cc(); nd != (Link_node*)NULL;
	 nd = pd) {
      pd = nd->get_next_cc();
      tree = (Lex_tree*)(nd->get_item_cc());
      lextree_list_d->remove_cc(nd);
      if (tree != (Lex_tree*)NULL) {
	delete tree;
      }
    }
    delete lextree_list_d;
    lextree_list_d = (Link_list*)NULL;
  }

  // free memory in word-level trace lists
  //
  for (int_4 i = 0; i < num_active_words_d; i++) {
    trlist = word_trlist_d[active_words_d[i]];
    if (trlist != (Link_list*)NULL) {
      for (nd = trlist->get_head_cc(); nd != (Link_node*)NULL; nd = pd) {
	pd = nd->get_next_cc();
	tr = (Trace*)(nd->get_item_cc());
	if (tr != (Trace*)NULL) {
	  manager_d->delete_cc(tr);
	}
	trlist->remove_cc(nd);
      }
    }
    delete trlist;
  }
  
  // free memory in phone-level trace lists
  //
  for (int_4 i = 0; i < num_active_models_d; i++) {
    trlist = model_trlist_d[active_models_d[i]];
    if (trlist != (Link_list*)NULL) {
      for (nd = trlist->get_head_cc(); nd != (Link_node*)NULL; nd = pd) {
	pd = nd->get_next_cc();
	tr = (Trace*)(nd->get_item_cc());
	if (tr != (Trace*)NULL) {
	  manager_d->delete_cc(tr);
	}
	trlist->remove_cc(nd);
      }
    }
    delete trlist;
  }

  // reset Communicator API parameters
  //
  size_d = 0;
  current_d = 0;

  // release memory for model-level segments (alignments)
  //
  if (segment_mode_d == DEC_MODEL_SEGMENT_MODE) {
    for (nd = model_seglist_d->get_head_cc();
	 nd != (Link_node*)NULL; nd = pd) {
      	pd = nd->get_next_cc();
	ele = (int_4*)(nd->get_item_cc());
	if (ele != (int_4*)NULL) {
	  delete ele;
	}
	model_seglist_d->remove_cc(nd);
    }
  }

  if (model_seglist_d != (Link_list*)NULL) {
    delete model_seglist_d;
    model_seglist_d = (Link_list*)NULL;
  }
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
