#include <Inventor/cve/SoMFNetListener.h>

SO_MFIELD_SOURCE(SoMFNetListener, SbNetListener*, SbNetListener*);


void SoMFNetListener::initClass(void)
{
  SO_MFIELD_INIT_CLASS(SoMFNetListener, SoMField);
}


void SoMFNetListener::append(SbNetListener *l)
{
  set1Value(getNum(), l);
  l->ref();
}


void SoMFNetListener::insert(SbNetListener *l, int idx)
{
  assert(idx >= 0 && idx < getNum());
  insertSpace(idx, 1);
  set1Value(idx, l);
  l->ref();
}


SbNetListener* SoMFNetListener::get(int idx) const
{
  assert(idx >= 0 && idx < getNum());
  return operator[](idx);
}


int SoMFNetListener::find(const SbNetListener *l) const
{
  const int c = getNum();
  const SbNetListener **a = getValues(0);
  int i;
  for (i=0; i<c; i++)
    if (a[i] == l)  return i;
  
  return -1;
}


void SoMFNetListener::remove(int idx)
{
  get(idx)->unref();
  deleteValues(idx, 1);
}


void SoMFNetListener::remove(SbNetListener *l)
{
  int idx = find(l);
  if (idx != -1)
    remove(idx);
}


void SoMFNetListener::removeAll()
{
  deleteValues(0);
}


void SoMFNetListener::replace(int idx, SbNetListener *l)
{
  assert(idx >= 0 && idx < getNum());
  SbNetListener *old = get(idx);
  if (old != l) {
    if (old)  old->unref();
    set1Value(idx, l);
    if (l)  l->ref();
  }
}


void SoMFNetListener::replace(SbNetListener *oldL, SbNetListener *newL)
{
  int idx = find(oldL);
  if (idx != -1)
    replace(idx, newL);
}


void SoMFNetListener::insertSpace(int start, int num)
{
  SbBool notificationOld = this->enableNotify(FALSE);

  // make default action
  inherited::insertSpace(start, num);

  // set inserted items to NULL
  const SbNetListener **a = getValues(0) + start;
  const SbNetListener **e = a + num;
  while (a<e) {
    (*a) = NULL;
    a++;
  }

  this->enableNotify(notificationOld);
  if (notificationOld)  this->valueChanged();
}


void SoMFNetListener::deleteValues(int start, int num)
{
  // unref all deleted values
  SbNetListener **a = (SbNetListener**)getValues(0) + start;
  SbNetListener **e = a + (num!=-1 ? num : getNum()-start);
  while (a<e) {
    if ((*a) != NULL)
      (*a)->unref();
    a++;
  }

  // make default action
  inherited::deleteValues(start, num);
}


//
// FOLLOWING code is taken from COIN sources. Copyright by SIM.
//


// Import a single node.
SbBool
SoMFNetListener::read1Value(SoInput * in, int index)
{
/*  SoSFNode sfnode;
  SbBool result = sfnode.readValue(in);
  if (result) this->set1Value(index, sfnode.getValue());
  return result;*/
  assert(0);
  return FALSE;
}

// Export a single node.
void
SoMFNetListener::write1Value(SoOutput * out, int idx) const
{
  // NB: This code is common for SoMFNode, SoMFPath and SoMFEngine.
  // That's why we check for the base type before writing.

/*  SoBase * base = (SoBase*) this->values[idx];
  if (base) {
    if (base->isOfType(SoNode::getClassTypeId())) {
      ((SoNode*)base)->writeInstance(out);
    }
    else if (base->isOfType(SoPath::getClassTypeId())) {
      SoWriteAction wa(out);
      wa.continueToApply((SoPath*)base);
    }
    else if (base->isOfType(SoEngine::getClassTypeId())) {
      ((SoEngine*)base)->writeInstance(out);
    }
  }
  else {
    out->write("NULL");
  }*/
  assert(0);
}
