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

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

// method: match
//
// arguments:
//  const Instance& instance: (input) instance to assign
//
// return: logical error status
//
// compares two instances for equality
//
boolean Instance::match(const Instance& instance_a) const {

  // compare the surrent symbol, current history and previous history
  //
  if ((symbol_d != instance_a.symbol_d) ||
      (history_d != instance_a.history_d) ||
      (symbol_stack_d != instance_a.symbol_stack_d)) {
    return false;
  }

  // compare the nsymbols
  //
  if ((long)nsymbol_length_d > 0) {
    
    for (long i = 0; i < (long)nsymbol_length_d; i++) {
      if (nsymbol_d[i] != instance_a.nsymbol_d[i]) {
	return false;
      }
    }
  }  

  // instances must be equal if we reached this point
  //
  return true;
}

// method: assign
//
// arguments:
//  const Instance& instance: (input) instance to assign
//
// return: logical error status
//
// assign instance from the input
//
boolean Instance::assign(const Instance& copy_instance_a) {

  // copy the internal data
  //
  frame_d = copy_instance_a.frame_d;
  score_d = copy_instance_a.score_d;
  skip_level_d = copy_instance_a.skip_level_d;
  skip_symbol_d = copy_instance_a.skip_symbol_d;
  lm_score_d = copy_instance_a.lm_score_d;    
  instance_mode_d = copy_instance_a.instance_mode_d;
  instance_state_d = copy_instance_a.instance_state_d;  
  
  // copy the symbol node pointer
  //
  symbol_node_d = copy_instance_a.symbol_node_d;
  
  // copy the history pointer
  //
  history_d = copy_instance_a.history_d;
  
  // copy the symbol pointer
  //
  symbol_d = copy_instance_a.symbol_d;

  // copy the symbol stack pointer
  //
  symbol_stack_d = copy_instance_a.symbol_stack_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_instance_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 instance
//
boolean Instance::clear(Integral::CMODE cmode_a) {

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

  // make sure the reference count is zero
  //
  if (reference_count_d > 0) {
    return Error::handle(name(), L"clear", Error::ARG, __FILE__, __LINE__);
  }

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

  // clear the symbol stack pointer
  //
  symbol_stack_d = (History*)NULL;  

  // clear the reference pointer
  //
  reference_vertex_d = (BiGraphVertex<TrainNode>*)NULL;
  
  // reset the member data
  //
  frame_d = DEF_FRAME;
  skip_level_d = DEF_SKIP_LEVEL;
  reference_count_d = DEF_COUNT;
  instance_mode_d = DEF_INSTANCE_MODE;
  instance_state_d = DEF_INSTANCE_STATE;  

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

// method: deleteInstance
//
// arguments:
//  Instance* in_instance: (input) the instance to delete
//  boolean is_recursive: (input) delete instances recursively
//  boolean clear_search_node: (input) delete instance list of the search node
//
// return: a boolean value indicating status
//
// discard this instance, backpointer instances and search nodes if necessary
//
boolean Instance::deleteInstance(Instance* in_instance_a,
	    boolean is_recursive_a,
	    boolean clear_search_node_a) {

  // declare local variables
  //
  Instance* back_ptr = in_instance_a->getBackPointer();
  Instance* curr_ptr = in_instance_a;

  if (curr_ptr == (Instance*)NULL) {
    return Error::handle(name(), L"deleteInstance", Error::ARG, __FILE__, __LINE__);
  }
  
  // clear the instance 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->clearInstanceList();
    }
  }
  else {
    if (tmp_node != (SearchNode*)NULL) {
      tmp_node->removeInstance(curr_ptr);
    }
  }
  
  // delete the current instance
  //
  delete curr_ptr;
  curr_ptr = (Instance*)NULL;

  // delete traces on the backpath whose reference count is zero
  //
  if (is_recursive_a) {
    
    while ((back_ptr != (Instance*)NULL) && (back_ptr->getRefCount() < 1)) {
      
      // delete the backpointer
      //
      curr_ptr = back_ptr;
      back_ptr = curr_ptr->getBackPointer();
  
      // clear the instance 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->clearInstanceList();
	}
      }
      else {
	if (tmp_node != (SearchNode*)NULL) {
	  tmp_node->removeInstance(curr_ptr);
	}
      }
      
      // delete the current instance
      //
      delete curr_ptr;
      curr_ptr = (Instance*)NULL;
    }
  }
    
  // exit gracefully
  //
  return true;
}
