//package TideCalendar
import javax.swing.ImageIcon;
/**
 * Class Queue creates a Queue data structure in a single linked list
 * format.
 *
 * @author Tim Bollman
 * @author Earthguide
 * @version 1.5 09-06-05
 */
public class MoonQueue
{
   /* Pointer to the first Node in Queue (for removal)*/
   public Node first;
   /* Pointer to the last Node in Queue (for insertion)*/
   public Node last;
   /* How many nodes are stored in the Queue*/
   private int occupancy = 0;
   private int size = 0;
   private Moon myMoon;
   /**
    * Removes the first element in the Queue and returns the data
    * stored in it.
    *
    * @return the element stored in the first element of the Queue or null if
    * no elements are stored in the Queue
    */
   public MoonQueue(int size, Moon moon)
   {
      this.size = size;
      myMoon = moon;
   }
   /**
    * Returns the Moon Picture at the specified day.
    *
    * @param day the day of the year that the moon is desired for
    * @return the ImageIcon at the specified location or null if location is
    * outside the specified bounds.
    */
   public ImageIcon getMoon(int day)
   {
      if (day < 0) return null;
      ImageIcon retVal = null;
      if (occupancy == 0)
      {
	 retVal = myMoon.getMoon(day*24);
	 byte type = myMoon.moonType(day);
	 if (type == 0);//doNothing
	 else 
	    retVal.setDescription((type==1)?"Full Moon":"New Moon");
	 first = new Node(retVal, null, null, day);
	 last = first;
	 occupancy++;
      }
      else if (day < first.getDay())
      {
	 retVal = myMoon.getMoon(day*24);
	 byte type = myMoon.moonType(day);
	 if (type == 0);//doNothing
	 else 
	    retVal.setDescription((type==1)?"Full Moon":"New Moon");
	 first = new Node(retVal, null, first, day);
	 occupancy++;
	 if (occupancy > size)
	 {
	    Node temp = last;
	    last = last.last;
	    temp.remove();
	    occupancy--;
	 }
      }
      else if (day > last.getDay())
      {
	 retVal = myMoon.getMoon(day*24);
	 byte type = myMoon.moonType(day);
	 if (type == 0);//doNothing
	 else 
	    retVal.setDescription((type==1)?"Full Moon":"New Moon");
	 last = new Node(retVal, last, null, day);
	 occupancy++;
	 if (occupancy > size) //remove the first element
	 {
	    Node temp = first;
	    first = first.next;
	    temp.remove();
	    occupancy--;
	 }
      }
      else
      {
	 //check to see if data is in list 
	 Node working = first;
	 for (int i = 0; i < occupancy; i++, working = working.next)
	 {
	    if (working.getDay() == day)
	       return working.data;
	    if (working.getDay() > day) //list is ordered sequentially, so if
	       break; //the working node's day is too far, all rest will be too.
	 }
	 //get moon
	 retVal = myMoon.getMoon(day*24);
	 byte type = myMoon.moonType(day);
	 if (type == 0);//doNothing
	 else 
	    retVal.setDescription((type==1)?"Full Moon":"New Moon");
	 //create node location
	 new Node(retVal, working.last, working, day);
	 occupancy++;
	 if (occupancy > size) //remove the last element
	 {
	    Node temp = last;
	    last = last.last;
	    temp.remove();
	    occupancy--;
	 }
      }
      return retVal;
   }
   public void printQueue()
   {
      Node working = first;
//      System.err.println("Queue Report: ");
//      System.err.println("Occupancy = " + occupancy);
      while (working != last)
      {
	 System.err.print(working.day + " => ");
	 working = working.next;
      }
      if (last != null)
	 System.err.println(last.day);
   }
   /**
    * Transforms the Queue into an array
    *
    * @return an array of ImageIcons representation of the Queue
    */
   public ImageIcon[] toArray()
   {
      if (occupancy == 0)
	 return null;
      int i;
      ImageIcon[] returnee = new ImageIcon[occupancy];
      Node working = first;
      for (i = 0; i < occupancy; i++, working = working.next)
	 returnee[i] = working.data;
      return returnee;
   }
   /**
    * removes all elements from the node
    */
   public void clear()
   {
      if (first == null) return;
      Node working = first;
      while(working.next != null)
      {
	 working = working.next;
	 (working.last).remove();
      }
      last.remove();
      first = null;
      last = null;
      occupancy = 0;
   }
   /**
    * returns the occupancy of this queue
    * @return the occupancy of this queue
    */
   public int length()
   {
      return occupancy;
   }

/**
 * Class Node stores the elements for the Queue.
 * 
 * @author Tim Bollman
 * @author Earthguide
 * @version 1.5 09-06-05
 */
   public class Node
   {
      //holds the node that comes after this node
      private Node next = null;
      //holds the node that comes after this node
      private Node last = null;
      //holds the data stored in the node
      private ImageIcon data;
      //extra check to ensure that the days match up.
      private int day;
      /**
       * Creates a Node with the specified ImageIcon as its data.
       *
       * @param ooo ImageIcon to be stored in the Node.
       */
      public Node(ImageIcon data, Node last, Node next, int day)
      {
	 this.data = data;
	 this.day = day;
	 this.last = last;
	 if (last != null)
	    last.next = this;
	 this.next = next;
	 if (next != null)
	    next.last = this;
      }
      public String toString()
      {
	 String retVal = data.toString();
	 if (next != null)
	 {
	    retVal += "::" + next.toString();
	 }
	 return retVal;
      }
      public void remove()
      {
	 if (last != null)
	    last.next = next;
	 if (next != null)
	    next.last = last;
	 data = null;
      }
      public int getDay()
      {
	 return day;
      }
   }
}
