// file: $isip/class/search/Trace/trace_06.cc
// version: $Id: trace_06.cc 9347 2003-11-26 20:46:15Z alphonso $
//

// isip include files
//
#include "Trace.h"

// method: assign
//
// arguments:
//  const Trace& copy_trace: (input) trace to copy
//
// return: logical error status
//
// assign trace from the copy
//
boolean Trace::assign(const Trace& copy_trace_a) {

  // copy the internal data for the trace
  //
  frame_d = copy_trace_a.frame_d;
  score_d = copy_trace_a.score_d;
  lm_score_d = copy_trace_a.lm_score_d;  
  trace_mode_d = copy_trace_a.trace_mode_d;

  // copy the history pointer
  //
  history_d = copy_trace_a.history_d;
  
  // copy the symbol pointer
  //
  symbol_d = copy_trace_a.symbol_d;

  // copy the symbol node
  //
  symbol_node_d = copy_trace_a.symbol_node_d;
  
  // copy the nsymbols
  //
  if ((long)nsymbol_length_d > 0) {
    
    if (nsymbol_d == (Context**)NULL) {
      nsymbol_d = new Context*[(long)nsymbol_length_d];
    }
    
    for (long i = 0; i < (long)nsymbol_length_d; i++) {
      nsymbol_d[i] = copy_trace_a.nsymbol_d[i];
    }
  }
  
  // exit gracefully
  //
  return true;
}

// method: clear
//
// arguments:
//  Integral::CMODE cmode: (input) clear mode
//
// return: a boolean value indicating status
//
// clear the contents of the trace
//
boolean Trace::clear(Integral::CMODE cmode_a) {

  // decrement the reference count for the back pointer
  //
  if (back_ptr_d != (Trace*)NULL) {
    back_ptr_d->decrementRefCount();   
  }

  // make sure the reference count is zero
  //
  if (reference_count_d > 0) {
    Error::handle(name(), L"destructor", Trace::ERR, __FILE__, __LINE__);
  }
  
  // clear the back pointer
  //
  back_ptr_d = (Trace*)NULL;

  // clear the history pointer
  //
  history_d = (History*)NULL;
  
  // clear the symbol pointer
  //
  symbol_d = (Context*)NULL;

  // clear the symbol node
  //
  symbol_node_d = (SymbolGraphNode*)NULL;
  
  // clear the reference pointer
  //
  reference_vertex_d = (BiGraphVertex<TrainNode>*)NULL;
  
  // reset the score
  //
  frame_d = DEF_FRAME;
  score_d = DEF_SCORE;
  lm_score_d = DEF_SCORE;  
  reference_count_d = DEF_COUNT;
  trace_mode_d = DEF_TRACE_MODE;

  // clear the nsymbols
  //
  if (nsymbol_d != (Context**)NULL) {
    delete nsymbol_d;
    nsymbol_d = (Context**)NULL;
  }
  
  // exit gracefully
  //
  return true;
}

// method: deleteTrace
//
// arguments:
//  Trace* in_trace: (input) the trace to delete
//  boolean is_recursive: (input) delete traces recursively
//  boolean clear_search_node: (input) delete trace list of the search node
//
// return: a boolean value indicating status
//
// discard this trace, backpointer traces and search nodes if necessary
//
boolean Trace::deleteTrace(Trace* in_trace_a, boolean is_recursive_a,
	       boolean clear_search_node_a) {

  // declare local variables
  //
  Trace* back_ptr = in_trace_a->getBackPointer();
  Trace* curr_ptr = in_trace_a;

  if (curr_ptr == (Trace*)NULL) {
    return Error::handle(name(), L"deleteTrace", Error::ARG, __FILE__, __LINE__);
  }
  
  // clear the trace list of the corresponding search node if required
  //
  GraphVertex<SearchNode>* vertex = (GraphVertex<SearchNode>*)NULL;
  if (curr_ptr->getSymbol() != (Context*)NULL) {
    vertex = curr_ptr->getSymbol()->getCentralVertex();
  }

  SearchNode* tmp_node = (SearchNode*)NULL;
  if (vertex != (GraphVertex<SearchNode>*)NULL) {
    tmp_node = vertex->getItem();
  }

  if (clear_search_node_a) {
    if (tmp_node != (SearchNode*)NULL) {
      tmp_node->clearTraceList();
    }
  }
  else {
    if (tmp_node != (SearchNode*)NULL) {
      tmp_node->removeTrace(curr_ptr);
    }
  }
  
  // delete the current trace
  //
  delete curr_ptr;
  curr_ptr = (Trace*)NULL;

  // delete traces on the backpath whose reference count is zero
  //
  if (is_recursive_a) {
    
    while ((back_ptr != (Trace*)NULL) && (back_ptr->getRefCount() < 1)) {
      
      // delete the backpointer
      //
      curr_ptr = back_ptr;
      back_ptr = curr_ptr->getBackPointer();
  
      // clear the trace list of the corresponding search node if required
      //
      vertex = (GraphVertex<SearchNode>*)NULL;
      if (curr_ptr->getSymbol() != (Context*)NULL) {
	vertex = curr_ptr->getSymbol()->getCentralVertex();
      }
      
      tmp_node = (SearchNode*)NULL;
      if (vertex != (GraphVertex<SearchNode>*)NULL) {
	tmp_node = vertex->getItem();
      }
      
      if (clear_search_node_a) {
	if (tmp_node != (SearchNode*)NULL) {
	  tmp_node->clearTraceList();
	}
      }
      else {
	if (tmp_node != (SearchNode*)NULL) {
	  tmp_node->removeTrace(curr_ptr);
	}
      }
      
      // delete the current trace
      //
      delete curr_ptr;
      curr_ptr = (Trace*)NULL;
    }
  }
  
  // exit gracefully
  //
  return true;
}
