/* Component.c */

#include<SYNERGY/Component.h>
#include<SYNERGY/ID.h>

/* Q?  : Are constructors for other objects in Component called recursively?, 
  automatic?, before or after the Component constructor */
 Component::Component()
{
  ID = IDdBase = nil;
}

 Component::Component(const string &localLabel,const &Component dBaseComponent)
{
  this->Component();

  /* New variables are not created with values of fields/ptrs =0, hence
     duplicate calls destructor which chokes trying to delete random pointers,
     so the above empty initializer resets pointers and values */

  /* First duplicate the database component */

  dBaseComponent.duplicate(this);
  
  /* change ID's to reflect new status */
  ID = new IDLabel(localLabel);
  this->dBaseComponent = false;
}

  /* used by duplicate */
 Component::Component(const IDLabel &ID, const IDLabel &IDdBase,
		      bool dBaseComponent)
{
  this->Component();

  this->ID = new IDLabel(ID);
  this->IDdBase = new IDLabel(IDdBase);
  this->dBaseComponent = dBaseComponent;
}


 Component::~Component(void)
{
  delete(ID); delete(IDdBase);
  delete(elements); delete(constraints); delete(components);
  /* now destructors of member functions are called by default */
  this->Component(); /* strange but effective way of nixing pointer values */
}

Component *Component::duplicate(Component *componentptr);
/* i create a complete copy including underlying structures  and
   children, useful for making copies of subsystems 
   this copy is placed in *componentptr */
{
  int i;

  /* First empty clear the data structures of all trash */
  componentptr->~Component();

  /* then do a complete copy */
  componentptr->componentptr(*ID,*IDdBase, true, dBaseComponent);
  componentptr->state.GenArray(state); /* Q? : check if OK */
  
  elements.duplicate(&componentptr->elements);
  constraints.duplicate(&componentptr->constraints);
  components.duplicate(&componentptr->components);

  return(componentptr);
}


 Component::Component(const Component &component)
{
  this->~Component();

  dBaseComponent = component.dBaseComponent;

  state.GenArray(component.state);

  /* copy pointers */
  ID = component.ID; 
  IDdBase = component.IDdBase;
  elements = component.elements;
  constraints = component.constraints;
  components = component.components;

}

Component& Component::operator=(const Component &component)
/* efficient copy, does not copy structures that are 
   constant temporally - HUH Q? */
{
}

GenPtr Component::accessAtom(const string &atomId)
{
  return(this->accessAtom(this->getIndex(atomId)));
}

int Component::getIndex (const string &atomId, ComponentPtr *cPtr)
{int eIndex, cIndex, index;
 ElementPtr ePtr;
 ComponentPtr tempPtr;

 string head = IDgetHead(atomId);
 string tail = IDgetTail(atomId);

 if IDisLabel(tail) /* then it belongs to one of the constituent components */
   {
     /* find the right component from the head, */
     if (!(cIndex = this->components.index(head)))
       {*cPtr = nil; return -2;}
     
     /* and ask that component to find the pointer & index */
     return (components[cIndex])->getIndex(tail, cPtr);
   }
 else
   {
     /* i am the right component */
     *cPtr = this;
     
     /* now find the right element from the head,  */
     eIndex = this->elements.index(head);
     if (eIndex) ePtr = elements[eIndex];
     else return -1;
     
     /* and access atom corresponding to the tail Q? */
     tail = IDstripSlash(tail);
     return(ePtr->index(tail));
   }
}
