/* nodeInterface.C: field, exposedField, eventIn, eventOut, ... base class  */

#include <string.h>
#include "xrmlP.H"
#include "file.H"

namespace xrml {

PoolImpl(interfaceMemberRef)
PoolImpl(interfaceMember)

bool interfaceMember::check_type(const fieldValue& refvalue)
{
  if (fieldType(this->value) != fieldType(refvalue)) {
    Error(NULL, "value type mismatch (this: %s, reference: %s)",
	  fieldTypeName(fieldType(this->value)),
	  fieldTypeName(fieldType(refvalue)));
    return false;
  }
  return true;
}

interfaceMember* interfaceMember::clone(void) 
{
  return new interfaceMember(*this);
}

void interfaceMember::instantiate(class SFNode* thisnode, class Proto* enclosing_proto) 
{ 
  /* do nothing */ 
}

interfaceMember* interfaceMember::get(const char *Id)
{
  return (strcmp(Id, this->Id) == 0) ? this : 0;
}

interfaceMember* interfaceMember::link(SFNode *thisnode, SFNode* srcnode, interfaceMember* srcifm)
{
  interfaceMember *link = 0;

  if (!check_type(srcifm->value))
    return 0;		// value type mismtach

  // test exposedField first since an exposedField is also a field, eventIn and eventOut
  if (!link && is_exposedField(srcifm))
    link = link_exposedField(thisnode, srcnode, dynamic_cast<exposedField*>(srcifm));
  if (!link && is_field(srcifm))
    link = link_field(thisnode, srcnode, dynamic_cast<field*>(srcifm));
  if (!link && is_eventIn(srcifm))
    link = link_eventIn(thisnode, srcnode, dynamic_cast<eventIn*>(srcifm));
  if (!link && is_eventOut(srcifm))
    link = link_eventOut(thisnode, srcnode, dynamic_cast<eventOut*>(srcifm));
  return link;
}

bool interfaceMember::assign(SFNode *, const fieldValue&)
{
  Error("interfaceMember::assign", "trying to assign to a non-field or exposedField");
  return false;
}

void interfaceMember::initialize(SFNode *, const fieldValue&)
{
  Error("interfaceMember::initialize", "trying to initialize to a non-field of exposedField");
}

void interfaceMember::process(SFNode *, const fieldValue&)
{
  Error("interfaceMember::process", "trying to process a non-eventIn or exposedField");
}

void interfaceMember::post(SFNode *, const fieldValue&)
{
  Error("interfaceMember::post", "trying to post a non-eventOut or exposedField");
}

void interfaceMember::dispatch(void) const
{
  Error("interfaceMember::dispatch", "trying to dispatch a non-eventOut or exposedField");
}

void interfaceMember::add_route(class SFNode *, class interfaceMember *)
{
  Error("interfaceMember::add_route", "trying to add a route to a non-eventOut or exposedField");
}

// only prints Id and value
ostream& interfaceMember::print_Id_value(ostream& s) 
{
  s.width(10);
  s.setf(ios::left,ios::adjustfield);
  s << ' ' << fieldTypeName(fieldType(value));
  s.width(14);
  s.setf(ios::left,ios::adjustfield);
  s << ' ' << (Id ? Id : "(null Id)") << '\t' << value << "\t(";
  if (timestamp == CONSTRUCT_TIME)
    s << "default";
  else
    s << "T" << timestamp;
  return s << ')';
}

ostream& interfaceMember::print(ostream& s) 
{
  return print_Id_value(s << "????????????");
}

void interfaceMemberRef::_init(SFNode *refnode, interfaceMember* refifm)
{
  interfaceMemberRef::refnode = refnode;

  if (refnode) {
    int i=0;	// locate ref interface member in linked node's interface
    while (i < refnode->nrInterfaceMembers && refnode->interface[i] != refifm) i++;
    assert(i < refnode->nrInterfaceMembers);
    interfaceMemberRef::refidx = i;
  } else
    interfaceMemberRef::refidx = -1;
}

ostream& interfaceMemberRef::print(ostream& s) 
{
  assert(refnode);
  return s << " -> " << refnode->name() << '.' << ref()->Id;
}

} // namespace xrml

