package com.mwc.util;

import java.io.*;

/**
 * A dobully linked circular linked list implementation.
 * 
 * @author Matthew W. Coan
 */
public class CListint implements Serializable {
   class Node implements Serializable {
      Node next, prev;
      int data;
      
      Node() { super(); }
   }
   
   /**
    * Used to iterate in both directrions.
    */
   public class Iterator {
      private Node _ptr;
      
      private Iterator(Node start) {
         _ptr = start;
      }
      
      public int data() { 
         return _ptr.data; 
      }
      
      public void setData(int data) {
         _ptr.data = data;
      }
      
      public boolean isEnd() {
         return _ptr == _head;
      }
      
      public boolean notEnd() {
         return _ptr != _head;
      }
      
      public boolean hasNext() {
         return (_ptr.next != _head);
      }
      
      public boolean hasPrev() {
         return (_ptr.prev != _head);
      }
      
      public void next() { 
         _ptr = _ptr.next;
      }
      
      public void prev() {
         _ptr = _ptr.prev;
      }
      
      public void remove() {
         _size--;
         Node temp = _ptr;
         _ptr.next.prev = _ptr.prev;
         _ptr.prev.next = temp.next;
         _ptr = temp.prev;
      }
   }
   
   private Node _head;
   private long _size;
   
   public CListint() {
      super();
      _head = new Node();
      _head.next = _head.prev = _head;
      _size = 0L;
   }
   
   public long size() { return _size; }
   
   public Iterator begin() { return new Iterator(_head.next); }
   public Iterator rbegin() { return new Iterator(_head.prev); }
   
   public void pushFront(int data) {
      Node n = new Node();
      n.data = data;
      _head.next.prev = n;
      n.next = _head.next;
      n.prev = _head;
      _head.next = n;
      _size++;
   }

   public void pushBack(int data) {
      Node n = new Node();
      n.data = data;
      _head.prev.next = n;
      n.prev = _head.prev;
      n.next = _head;
      _head.prev = n;
      _size++;
   }
   
   public void insertBefore(Iterator ptr, int data) {
      Node n = new Node();
      n.data = data;
      ptr._ptr.prev.next = n;
      n.prev = ptr._ptr.prev;
      n.next = ptr._ptr;
      ptr._ptr.prev = n;
      _size++;
   }
   
   public void insertAfter(Iterator ptr, int data) {
      Node n = new Node();
      n.data = data;
      ptr._ptr.next.prev = n;
      n.next = ptr._ptr.next;
      n.prev = ptr._ptr;
      ptr._ptr.next = n;
      _size++;
   }
}
