#include <config.h>
#include <graph/Node.h>
#include <graph/NodeError.h>
#include <graph/NodeNameTab.h>

using std::set;
using std::string;

Node::Node(Index const &dim)
  : _parents(), _children(), _ref(0), data(dim)
{
}

Node::~Node()
{
  unlink();
}

void Node::ref()
{
  _ref++;
}

void Node::unref()
{
  _ref--;
  if (_ref == 0) {
    delete this;
  }
}

unsigned int Node::refCount()
{
  return _ref;
}

set<Node*> const &Node::parents() const
{
  return _parents;
}


set<Node*> const &Node::children() const
{
  return _children;
}


void Node::addParent(Node *node)
{
  if (this == node) {
    throw NodeError(this, "Node cannot be its own parent");
  }
  _parents.insert(node);
  node->_children.insert(this);
}


void Node::removeParent(Node *node)
{
  _parents.erase(node);
  node->_children.erase(this);
}


void Node::unlink()
{
  set<Node*>::iterator p;
  
  for (p = _parents.begin(); p != _parents.end(); p++) {
    (*p)->_children.erase(this);
  }
  for (p = _children.begin(); p != _children.end(); p++) {
    (*p)->_parents.erase(this);
  }
  _parents.clear();
  _children.clear();
}

bool Node::isInitialized()
{
  double const *value = data.value();
  long length = data.length();

  for (long i = 0; i < length; i++) {
    if (value[i] == JAGS_NA)
      return false;
  }
  return true;
}

void Node::initialize()
{
  if (isInitialized()) {
    throw NodeError(this, "Attempt to reinitialize node");
  }
  else if (!canInitialize()) {
    throw NodeError(this,"Attempt to initialize node before its parents");
  }
  else {
    forwardSample();
  }
}

bool Node::canInitialize()
{
  for (set<Node*>::iterator i = _parents.begin(); i != _parents.end(); i++) {
    if (!(*i)->isInitialized()) {
      return false;
    }
  }
  return true;
}

string Node::name(NodeNameTab const &name_table) const
{
  return name_table.getName(this);
}

bool isObserved(Node const *node)
{
  return node->data.isFixed();
}


syntax highlighted by Code2HTML, v. 0.9.1