// file: $isip/class/search/SymbolGraphNode/SymbolGraphNode.h
// version: $Id: SymbolGraphNode.h 9373 2003-12-22 22:07:43Z alphonso $
//

// make sure definitions are only made once
//
#ifndef ISIP_SYMBOL_GRAPH_NODE
#define ISIP_SYMBOL_GRAPH_NODE

// isip include files
//
#ifndef ISIP_STRING
#include <String.h>
#endif

#ifndef ISIP_LONG
#include <Long.h>
#endif

#ifndef ISIP_FLOAT
#include <Float.h>
#endif

#ifndef ISIP_SINGLE_LINKED_LIST
#include <SingleLinkedList.h>
#endif

// forward class definitions
//
class SymbolGraph;

// SymbolGraphNode: a class to hold the data specific to a symbol graph
//
class SymbolGraphNode {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  

  static const String DEF_PARAM;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------  

  // default values
  //
  static const long DEF_NODE_INDEX = 0;  
  static const long DEF_FRAME_INDEX = -1;
  static const long DEF_REFERENCE_COUNT = 0;
  static const long DEF_IN_DEGREE = 0;
  static const long DEF_OUT_DEGREE = 0;    
  static const float DEF_SCORE = 0.0;
  
  //---------------------------------------
  //
  // error codes
  //
  //---------------------------------------

  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // define the symbol index
  //
  String symbol_d;

  // define the frame index
  //
  Long node_index_d;
  
  // define the frame index
  //
  Long frame_index_d;

  // define the reference count for this node
  //
  Long reference_count_d;
  
  // define the node statistics
  //
  Long num_arcs_in_d;
  Long num_arcs_out_d;

  // define the maximum path score for this node
  //
  Float score_d;

  // define incoming and outgoing connections
  //
  SingleLinkedList<SymbolGraphNode> prev_nodes_d;
  SingleLinkedList<SymbolGraphNode> next_nodes_d;  

  // define the list of previous scores
  //
  SingleLinkedList<Float> prev_scores_d;
  SingleLinkedList<Float> prevlm_scores_d;
  
  // define the forward acoustic and language model scores
  //
  SingleLinkedList<Float> lm_scores_d;
  SingleLinkedList<Float> ac_scores_d;

  // define the pointer to the parent graph
  //
  SymbolGraph* parent_graph_d;
  
  // define a static memory manager
  //
  static MemoryManager mgr_d;
  
  // define a static debug level
  //
  static Integral::DEBUG debug_level_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // method: setDebug
  //
  static boolean setDebug(Integral::DEBUG debug_level) {
    debug_level_d = debug_level;
    return true;
  }
  
  // method: destructor
  //
  ~SymbolGraphNode() {
    clear();
  }

  // method: default constructor
  //
  SymbolGraphNode();

  // method: constructor
  //
  SymbolGraphNode(long index, const String& symbol);

  // method: copy constructor
  //
  SymbolGraphNode(const SymbolGraphNode& copy_node) {
    assign(copy_node);
  }

  // method: assign
  //
  boolean assign(const SymbolGraphNode& copy_node) {
    return Error::handle(name(), L"assign", Error::ARG, __FILE__, __LINE__);
  }
  
  // method: operator=
  //
  SymbolGraphNode& operator=(const SymbolGraphNode& arg) {
    assign(arg);
    return *this;
  }
  
  // i/o methods
  //
  long sofSize() const;

  // read methods
  //
  boolean read(Sof& sof, long tag, const String& cname = CLASS_NAME);
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT, boolean param = true,
                   boolean nested = false);
  
  // write methods
  //
  boolean write(Sof& sof, long tag, const String& cname = CLASS_NAME) const;
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // method: eq
  //
  boolean eq(const SymbolGraphNode& obj) const {
    return (this == &obj);
  }
  
  // method: new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }

  // clear method
  //
  boolean clear(Integral::CMODE ctype = Integral::DEF_CMODE);
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------

  // method: getScore
  //
  float getScore() const {
    return score_d;
  }

  // method: setScore
  //
  boolean setScore(const float arg) {
    return (score_d = arg);
  }

  // method: getFrameIndex
  //
  long getFrameIndex() const {
    return frame_index_d;
  }

  // method: setFrameIndex
  //
  boolean setFrameIndex(const long arg) {
    return (frame_index_d = arg);
  }

  // method: getNodeIndex
  //
  long getNodeIndex() const {
    return node_index_d;
  }

  // method: setNodeIndex
  //
  boolean setNodeIndex(const long arg) {
    return (node_index_d = arg);
  }  

  // method: getSymbol
  //
  boolean getSymbol(String& arg) {
    return arg.assign(symbol_d);
  }
  
  // method: setSymbol
  //
  boolean setSymbol(const String& arg) {
    return symbol_d.assign(arg);
  }    

  // method: getIncoming
  //
  long getIncoming() const {
    return num_arcs_in_d;
  }

  // method: getOutgoing
  //
  long getOutgoing() const {
    return num_arcs_out_d;
  }

  // method: getRefCount
  //
  long getRefCount() {
    return reference_count_d;
  }

  // method: incrementRefCount
  //
  boolean incrementRefCount() {
    reference_count_d++;
    return true;
  }

  // method: decrementRefCount
  //
  boolean decrementRefCount() {
    reference_count_d--;
    return true;
  }

  // method: getParentGraph
  //
  SymbolGraph* getParentGraph() const {
    return parent_graph_d;
  }

  // method: setParentGraph
  //
  boolean setParentGraph(SymbolGraph* ptr) {
    parent_graph_d = ptr;
    return true;
  }  

  // method: getPrevNodesList
  //
  SingleLinkedList<SymbolGraphNode>& getPrevNodesList() {
    return prev_nodes_d;
  }

  // method: getNextNodesList
  //
  SingleLinkedList<SymbolGraphNode>& getNextNodesList() {
    return next_nodes_d;
  }  

  // method: getPrevScoresList
  //
  SingleLinkedList<Float>& getPrevScoresList() {
    return prev_scores_d;
  }

  // method: getPrevLMScoresList
  //
  SingleLinkedList<Float>& getPrevLMScoresList() {
    return prevlm_scores_d;
  }

  // method: getLMScoresList
  //
  SingleLinkedList<Float>& getLMScoresList() {
    return lm_scores_d;
  }

  // method: getScoresList
  //
  SingleLinkedList<Float>& getScoresList() {
    return ac_scores_d;
  }        

  // get scores method
  //
  boolean getScores(SymbolGraphNode* node, float& lm_score, float& ac_score);
  
  // insert methods
  //
  boolean insertPrevNode(SymbolGraphNode*& node, float score,
			 long max_hist, float lm_score);
  boolean insertNextNode(SymbolGraphNode*& node, float lm_score, float ac_score);

  boolean insertNode(SymbolGraphNode* node, SymbolGraphNode** lnode,
		     long*& map_list);  
  boolean insertNode(SymbolGraphNode* node, float lm_score,
		     float ac_score, SymbolGraphNode** lnode,
		     long*& map_list);
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

};

// include the context class here circumvent the circular dependency
//
#ifndef ISIP_SYMBOL_GRAPH
#include <SymbolGraph.h>
#endif

// end of include file
//
#endif
