/* SFNode.C */

#include <string.h>
#include <strstream.h>
#include "vrml.H"
#include "error.H"

void SFNode::construct(const char *id, const int nr, const interfaceDeclaration *iface)
{
  // filename of file being parsed and line at which parsing is going on
  // declared in yacc.y.
  extern char *yyfilename;
  extern int lineno;

  typeId = id;
  nameId = 0;
  nameIndex = -1;

  nrInterfaceDeclarations = nr;
  if (nr > 0) {
    interface = new interfaceDeclaration[nr];
    for (int i=0; i<nr; i++)
      interface[i] = iface[i];
  } else
    interface = 0;

  filename = yyfilename;
  line = lineno;

  clock = 0;
  client_data.i = 0;
  client_data.p = 0;

  isParent = false;
}

void SFNode::destruct(void)
{
  delete[] interface;
}

SFNode::SFNode(const char* id, const int nr, const interfaceDeclaration* iface)
{
  construct(id, nr, iface);
}

SFNode::SFNode(const SFNode& src)
{
  construct(src.typeId, src.nrInterfaceDeclarations, src.interface);
}

SFNode& SFNode::operator=(const SFNode& src)
{
  if (this != &src) {
    destruct();
    construct(src.typeId, src.nrInterfaceDeclarations, src.interface);
  }
  return *this;
}

SFNode::~SFNode()
{
  destruct();
}

void SFNode::instantiate_interface(Proto *master)
{
  for (int i=0; i<nrInterfaceDeclarations; i++)
    interface[i].instantiate(master);
}

SFNode* SFNode::instantiate(Proto *master)
{
  SFNode *instance = new SFNode(*this);
  instance->instantiate_interface(master);
  return instance;
}

#define MAXSFNODENAMELEN 1000
char* SFNode::name(char *buf)
{
  if (!buf) {
    static char sbuf[MAXSFNODENAMELEN];
    buf = sbuf;
  }
  ostrstream ost(buf,MAXSFNODENAMELEN);

  ost << typeId;
  if (nameId) 
    ost << ' ' << nameId << '(' << nameIndex << ')';
  if (filename && line>0)
    ost << '@' << filename << ':' << line;
  ost << '\0';

  return buf;
}

ostream& SFNode::print(ostream& s)
{
  s << name() << " {\n";
  for (int i=0; i<nrInterfaceDeclarations; i++)
    s << interface[i];
  return s << "}";
}

interfaceDeclaration* SFNode::get_field(char *fieldId)
{
  int i; interfaceDeclaration *d;
  for (i=0, d=interface; i<nrInterfaceDeclarations; i++, d++) {
    if ((d->kind==kfield || d->kind==kexposedField) &&
	strcmp(d->Id, fieldId) == 0)
      return d;
  }
  return 0;
}

interfaceDeclaration* SFNode::get_eventIn(char *eventInId)
{
  int i; interfaceDeclaration *d;
  for (i=0, d=interface; i<nrInterfaceDeclarations; i++, d++) {
    if (d->kind==keventIn && strcmp(d->Id, eventInId) == 0)
      return d;
  }
  return 0;
}

interfaceDeclaration* SFNode::get_eventOut(char *eventOutId)
{
  int i; interfaceDeclaration *d;
  for (i=0, d=interface; i<nrInterfaceDeclarations; i++, d++) {
    if (d->kind==keventOut && strcmp(d->Id, eventOutId) == 0)
      return d;
  }
  return 0;
}

void SFNode::render(void)
{
  Warning("SFNode::render", "can't yet render %s nodes", typeId);
}
