//
//      Roman Digital Clock
//      Written by: Larry Coffey
//
import java.applet.Applet;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 *      TutorialTwo is the main class for the TutorialTwo applet.
 *
 *      @author     Larry Coffey
 *      @version    0.01, 19 March 2010
 */
public class TutorialTwo extends Applet implements Runnable
{
   /** Serial version ID as required by serializable classes */
   private static final long    serialVersionUID = 1L;
   /** Size of the applet area */
   private Dimension            appletSize = null;
   /** Timer thread object used to signal refreshing the clock */
   private volatile Thread      timerThread = null;
   /** Font object used to draw Roman digits */
   private Font                 digitsFont = null;
   /** Paired lookup table used by the "toRoman" method */
   private StringIntPair        tableNumerals[] =
   {
      new StringIntPair ("M", 1000),
      new StringIntPair ("CM", 900),
      new StringIntPair ("D", 500),
      new StringIntPair ("CD", 400),
      new StringIntPair ("C", 100),
      new StringIntPair ("XC", 90),
      new StringIntPair ("L", 50),
      new StringIntPair ("XL", 40),
      new StringIntPair ("X", 10),
      new StringIntPair ("IX", 9),
      new StringIntPair ("V", 5),
      new StringIntPair ("IV", 4),
      new StringIntPair ("I", 1)
   };

   /**
    *       Constructor for the TutorialTwo class.
    */
   public TutorialTwo ()
   {
      // Initialize member variables
      System.out.println ("Tutorial: Constructor");
      timerThread = null;
      digitsFont = null;
   }

   /**
    *       Returns information about the author.
    *
    *       @return     Applet author information string
    */
   public String getAppletInfo ()
   {
      return ("Written by Larry Coffey, Copyright (c) 2010 SillyTutu.com, Inc.");
   }

   /**
    *       Called by the browser or applet viewer to inform this applet that it has been loaded into the system.
    */
   public void init ()
   {
      System.out.println ("Tutorial: init");
      appletSize = getSize ();
      digitsFont = new Font ("Serif", Font.BOLD, 48);
   }

   /**
    *       Called by the browser or applet viewer to inform this applet that it should start its execution.
    */
   public void start ()
   {
      System.out.println ("Tutorial: start");
      timerThread = new Thread (this);
      timerThread.start ();
   }

   /**
    *      Called by the browser or applet viewer to inform this applet that it should stop its execution.
    */
   public void stop ()
   {
      System.out.println ("Tutorial: stop");
      timerThread = null;
   }

   /**
    *      Called by the browser or applet viewer to inform this applet that it is being reclaimed
    *      and that it should destroy any resources that it has allocated.
    */
   public void destroy ()
   {
      System.out.println ("Tutorial: destroy");
   }

   /**
    *      Executes the main thread of this applet.
    */
   public void run ()
   {
      Thread currentThread = Thread.currentThread ();
      while (currentThread == timerThread)
      {
         repaint ();
         try {Thread.sleep (500);}
         catch (InterruptedException e) {e.printStackTrace ();};
      }
   }

   /**
    *       Repaints the canvas
    *
    *       @param  g       Graphics context
    */
   public void paint (Graphics g)
   {
      GregorianCalendar     currentDate;
      int                   s, m, h, width, height, x, y;
      String                timeString;
      FontMetrics           fm;

      // Get the current time and convert it to Roman numerals
      currentDate = new GregorianCalendar ();
      s = currentDate.get (Calendar.SECOND);
      m = currentDate.get (Calendar.MINUTE);
      h = currentDate.get (Calendar.HOUR);
      timeString = "" + toRoman (h) + " : " + toRoman (m) + " : " + toRoman (s);

      // Set the font, and calculate the size of the string
      g.setFont (digitsFont);
      fm = g.getFontMetrics ();
      width = fm.stringWidth (timeString);
      height = fm.getHeight ();

      // Calculate the string position and draw it centered
      x = (appletSize.width - width) / 2;
      y = ((appletSize.height - height) / 2) + fm.getAscent ();
      g.drawString (timeString, x, y);
   }

   /**
    *       Converts a given value into a string of Roman digits.
    *
    *       @param  number      Value to convert
    *
    *       @return             String of Roman numerals
    */
   private String toRoman (int number)
   {
      String	romanString;
      int		i;

      // Number out of range
      if ((number < 0) || (number > 4000))
    	  return ("-");

      // Cheating: Romans didn't have a zero
      if (number == 0)
    	  return ("0");

      romanString = "";
      for (i = 0; i < tableNumerals.length; i++)
      {
          while (number >= tableNumerals[i].integer)
          {
             number -= tableNumerals[i].integer;
             romanString += tableNumerals[i].string;
          }
      }
      return (romanString);
   }

   /**
    *       Class used to implement a string and integer paired value data structure.
    *
    *       @author     Larry Coffey
    */
   class StringIntPair
   {
      /** String component of the pair */
      String    string;
      /** Integer component of the pair */
      int       integer;
      /**
       *        Constructor for the StringIntPair class.
       *
       *        @param  string      Initial string value
       *        @param  integer     Initial integer value
       */
      StringIntPair (String string, int integer)
      {
         this.string = string;
         this.integer = integer;
      }
   }
}
