/* $Id: list.cc,v 1.1 1998/08/17 20:23:26 cthulhu Exp $ */

#include <iostream.h>
#include "list.hh"

#include "event.hh"

#define NOMEM_ACTION return NULL

template <class ElemType>
int Node<ElemType>::IsFirst ()
{
  if(element==NULL)
    return(-1);
  if(prev==NULL)
    return(1);
  return(0);
}

template <class ElemType>
int Node<ElemType>::IsLast ()
{
  if(element==NULL)
    return(-1);
  if(next==NULL)
    return(1);
  return(0);
}

template <class ElemType>
Lista<ElemType>::Lista ()
{
  num_elements = 0;
  head = NULL;
  tail = NULL;
}

template <class ElemType>
ElemType* Lista<ElemType>::GetHead ()
{
  return head->element;
}

template <class ElemType>
ElemType* Lista<ElemType>::GetTail ()
{
  return tail->element;
}

template <class ElemType>
ElemType* Lista<ElemType>::RemoveHead ()
{
  return RemoveAt(head);
}

template <class ElemType>
ElemType* Lista<ElemType>::RemoveTail ()
{
  return RemoveAt(tail);
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::AddHead (ElemType* elem)
{
  Node<ElemType> *new_node = new Node<ElemType>;
  if (!new_node)
    NOMEM_ACTION;

  new_node->prev = NULL;
  new_node->next = head;
  new_node->element = elem;

  if (head == NULL)
    tail = new_node;
  else
    head->prev = new_node;

  head = new_node;
  num_elements++;
  return head;
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::AddTail (ElemType* elem)
{
  Node<ElemType> *new_node = new Node<ElemType>;
  if (!new_node)
    NOMEM_ACTION;

  new_node->prev = tail;
  new_node->next = NULL;
  new_node->element = elem;

  if (tail == NULL)
    head = new_node;
  else
    tail->next = new_node;

  tail = new_node;
  num_elements++;
  return tail;
}

template <class ElemType>
void Lista<ElemType>::RemoveAll ()
{
  while (!IsEmpty())
    RemoveHead();
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::GetHeadPosition ()
{
  return head;
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::GetTailPosition ()
{
  return tail;
}

template <class ElemType>
ElemType* Lista<ElemType>::GetNext (Node<ElemType>* *node)
{
  ElemType* elem;

  elem = (*node)->element;
  *node = (*node)->next;
  return elem;
}

template <class ElemType>
ElemType* Lista<ElemType>::GetPrev (Node<ElemType>* *node)
{
  ElemType* elem;

  elem = (*node)->element;
  *node = (*node)->prev;
  return elem;
}

template <class ElemType>
ElemType* Lista<ElemType>::GetAt (Node<ElemType>* node)
{
  return node->element;
}

template <class ElemType>
ElemType* Lista<ElemType>::SetAt (Node<ElemType>* node, ElemType* elem)
{
  ElemType* old_elem;

  old_elem = node->element;
  node->element = elem;
  return old_elem;
}

template <class ElemType>
ElemType* Lista<ElemType>::RemoveAt (Node<ElemType>* node)
{
  ElemType* old_elem;

  old_elem = node->element;
  if (node->prev == NULL)
    head = node->next;
  else 
    node->prev->next = node->next;
  if (node->next == NULL)
    tail = node->prev;
  else
    node->next->prev = node->prev;
  delete node;
  num_elements--;
  return old_elem;
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::InsertBefore (Node<ElemType>* pnode, ElemType* elem)
{
  Node<ElemType> *new_node;

  if (pnode == NULL)
    return AddHead (elem);
  if (pnode->prev == NULL)
    return AddHead (elem);
  
  new_node = new Node<ElemType>;
  if (!new_node)
    NOMEM_ACTION;

  new_node->prev = pnode->prev;
  new_node->next = pnode;
  new_node->prev->next = new_node;
  new_node->next->prev = new_node;
  new_node->element = elem;
  num_elements++;
  return new_node;
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::InsertAfter (Node<ElemType>* pnode, ElemType* elem)
{
  Node<ElemType>* new_node;

  if (pnode == NULL)
    return AddTail (elem);
  if (pnode->next == NULL)
    return AddTail (elem);

  new_node = new Node<ElemType>;
  if (!new_node)
    NOMEM_ACTION;

  new_node->prev = pnode;
  new_node->next = pnode->next;
  new_node->prev->next = new_node;
  new_node->next->prev = new_node;
  new_node->element = elem;
  num_elements++;
  return new_node;
}


template <class ElemType>
void Lista<ElemType>::MergeList (Lista<ElemType> list2)
{
  if (list2.IsEmpty()) {
    list2.RemoveAll();
    return;
  }
  if (IsEmpty()) {
    head = list2.head;
    tail = list2.tail;
    num_elements = list2.num_elements;
    list2.RemoveAll();
    return;
  }
  num_elements += list2.num_elements;
  list2.head->prev = tail;
  tail->next = list2.head;
  tail = list2.tail;
  list2.RemoveAll();
}


template <class ElemType>
Node<ElemType>* Lista<ElemType>::Find (ElemType* elem)
{
  Node<ElemType> *pos1, *pos2;

  for (pos1 = GetHeadPosition(); (pos2 = pos1) != NULL;)
    if (elem == GetNext (&pos1))
      break;
  return pos2;
}

template <class ElemType>
Node<ElemType>* Lista<ElemType>::FindIndex (UINT index)
{
  Node<ElemType>* node;
  UINT i;

  if (num_elements <= index)
    return NULL;
  node = head;
  for (i = 0; i < index; i++, node = node->next);
  return node;
}

template <class ElemType>
UINT Lista<ElemType>::GetCount ()
{
  return num_elements;
}

template <class ElemType>
int Lista<ElemType>::IsEmpty ()
{
  return (!num_elements);
}

template class Lista<Event>;
template class Node<Event>;

/* $Log: list.cc,v $
 * Revision 1.1  1998/08/17 20:23:26  cthulhu
 * Initial revision
 * */
