#include "list.h"

list l_empty(void)
{
  return NIL;
}

int l_isempty(list l)
{
  return (l==NIL);
}

list l_insert(elem e, pos next, list l)
{
  pos new;
  pos prev;
  if(new=(pos)malloc(sizeof(struct liststruct)))
  {
    int i;
    new->value=e;
    prev=l_prev(next,l);
    if(!prev)
    {
      if(!next) /* if the list is empty */
      {
	new->next=NIL;
	new->prev=NIL;
	return new;
      }
      else /* if we insert it first */
      {
	new->next=next;
	new->prev=NIL;
	next->prev=new;
	return new;
      }
    }
    else
    {
      if(!next) /* if we insert it last */
      {
	new->next=NIL;
	new->prev=prev;
	prev->next=new;
	return l;
      }
      else /* if we insert it somewhere in the middle */
      {
	new->next=next;
	new->prev=prev;
	next->prev=new;
	prev->next=new;
	return l;
      }
    }
  }
  else
    return NIL;
}

list l_remove(pos p, list l)
{
  pos prev, next;
  if(!l)
    return NIL;
  prev=l_prev(p,l);
  next=l_next(p,l);
  if(!prev)
  {
    if(!next) /* if p is the only element */
    {
      free(p);
      return NIL;
    }
    else      /* if p is the first element */
    {
      free(p);
      next->prev=NIL;
      return next;
    }
  }
  else
  {
    if(!next) /* if p is the last element */
    {
      free(p);
      prev->next=NIL;
      return l;
    }
    else /* if p is somewhere in the middle */
    {
      free(p);
      next->prev=prev;
      prev->next=next;
      return l;
    }
  }
}

pos l_first(list l)
{
  if(l_isempty(l))
    return NIL;
  return l;
}

pos l_last(list l)
{
  pos p, prev;
  if(l_isempty(l))
    return NIL;
  p=l_first(l);
  while(p)
  {
    prev=p;
    p=l_next(p,l);
  }
  return prev;
}

pos l_prev(pos p, list l)
{
  if(l_isempty(l))
    return NIL;
  if(!p)
    return l_last(l);
  return p->prev;
}

pos l_next(pos p, list l)
{
  if(l_isempty(l))
    return NIL;
  if(!p)
    return l_first(l);
  return p->next;
}

void l_show(list l)
{
  pos p;
  printf("[ ");
  p=l_first(l);
  while(p)
  {
    showelem("(",p->value,") ");
    p=l_next(p, l);
  }
  printf("]\n");
}

elem l_value(pos p, list l)
{
  return p->value;
}

