/**
 * A class that represents queues of patients. This can be used, e.g.,
 * for a hospital waiting list.
 * @author Derek Bridge 666 d.bridge@cs.ucc.ie
 */
public class QueueOfPatients
{

/* =======================================================================
       PUBLIC INTERFACE
   =======================================================================
*/

/* --Getters----------------------------------------------------------- */

   /**
    * Returns true if and only if this queue is empty.
    * @return true if the queue is empty; false otherwise.
    */
   public boolean isEmpty()
   {  return size == 0;
   }

   /**
    * Returns the size of the queue.
    * @return the number of patients in this queue.
    */
   public int size()
   {  return size;
   }

   /**
    * Returns the patient object at the front of the queue.
    * It does not remove the object from the front of the queue;
    * it simply returns it.
    * The queue must not be empty.
    *
    * @return the patient object who is at the front of the queue.
    */
   public Patient front()
   {  if (isEmpty())
      {  System.out.println("QueueOfPatients Error:");
         System.out.println(
            "You have tried to return the patient at the front of an empty queue.");
         System.out.println("Program will continue but may crash subsequently.");
         return null;
      }
      else // non-empty queue
      {  return head.patient;
      }
   }

/* --Setters----------------------------------------------------------- */

   /**
    * Inserts a patient at the rear of the queue.
    * @param aPatient the patient being inserted.
    */
    public void enqueue(Patient aPatient)
    {  Node n = new Node(aPatient, null);
       if (isEmpty())
       {  head = n;
       }
       else
       {  tail.next = n;
       }
       tail = n;
       size++;
    }

   /**
    * Removes and returns the patient who is at the 
    * front of the queue.
    * The queue must not be empty
    * @return the patient who is at the front of the queue.
    */
   public Patient dequeue()
   {  if (! isEmpty())
      {  Patient front = head.patient;
         if (head == tail)
         {  head = null;
            tail = null;
         }
         else
         {  head = head.next;
         }
         size--;
         return front;
      }
      else
      {  System.out.println("QueueOfPatients Error:");
         System.out.println(
            "You have tried to return the patient at the front of an empty queue.");
         System.out.println("Program will continue but may crash subsequently.");
         return null;
      }
   }

/* =======================================================================
       MEMBER CLASSES
   =======================================================================
*/
   /*
    * Linked list nodes in a singly-linked list. Each node is a patient.
    */
   private class Node
   {
      /*
       * Allocates a new node for a singly-linked list.
       * This node `points to' the given node.
       * @param aPatient the patient to be stored at this node.
       * @param aNode the node that this new node will `point to'.
       */
      private Node(Patient aPatient, Node aNode)
      {  patient = aPatient;
         next = aNode;
      }

      private Patient patient;
      private Node next;
   }

/* =======================================================================
       INSTANCE VARIABLES & CLASS VARIABLES
   =======================================================================
*/

   /* We maintain pointers to the head and the tail. This makes insertion 
      and removal constant time operations.
    */

   /**
    * A pointer to the head of the queue.
    */
   private Node head = null;

   /** 
    * A pointer to the tail of the queue.
    */
   private Node tail = null;

   /**
    * The number of patients in the queue.
    */
   private int size = 0;
}
