import java.awt.*;
import java.applet.Applet;
import java.util.*;
import java.awt.image.*; 

/**
 * Class SBB_Uhr - the famous clock of the Swiss Railway (SBB: Schweizerische Bundesbahn)
 * created with BlueJ
 * 
 * @author (Martin Lieberherr) 
 * @version (May 17th, 2011) 
 */
public class SBB_Uhr extends Applet implements Runnable
{  
    int nx = 400; // width of applet window in pixel
    int ny = nx; // height of applet window in pixel
    int r = Math.round(nx/2);   // radius of circle
    int cx = r;  // x-coordinate of center of circle
    int cy = r;  // y-coordinate of c. of circle
    double co, si, t;      // time / temp. var.
    int[] drawHandx = new int[4];
    int[] drawHandy = new int[4];
    int[] hourHandx = new int[4];
    int[] hourHandy = new int[4];
    int[] minHandx = new int[4];
    int[] minHandy = new int[4];
    int[] secHandx = new int[4];
    int[] secHandy = new int[4];
    // buffered image for display of clock without hands
    BufferedImage  BuffImage1 = new BufferedImage(nx, ny, BufferedImage.TYPE_INT_RGB);
    Graphics g1 = BuffImage1.createGraphics();
    // buffered image for display of clock with hands
    BufferedImage  BuffImage2 = new BufferedImage(nx, ny, BufferedImage.TYPE_INT_RGB);
    Graphics g2 = BuffImage2.createGraphics();
    
    Thread thread;
    
 
    public void init()
    {
       // draw clock without hands in buffered image 
       g1.setColor(Color.white);
       g1.fillRect(0,0,nx,ny); 
       g1.setColor(Color.lightGray);
       g1.fillOval(1,1,nx-2,ny-2);  
       g1.setColor(Color.white);
       g1.fillOval((int) (0.025*nx), (int) (0.025*ny) , (int) (0.95*nx) , (int) (0.95*ny) );  
       g1.setColor(Color.black);
       
       // draw the hour-marks
       hourHandx[0] = (int) Math.round(0.025*r);
       hourHandy[0] = (int) Math.round(0.7*r);
       hourHandx[1] = (int) Math.round(0.025*r);
       hourHandy[1] = (int) Math.round(0.9*r);
       hourHandx[2] = (int) Math.round(-0.025*r);
       hourHandy[2] = (int) Math.round(0.9*r);
       hourHandx[3] = (int) Math.round(-0.025*r);
       hourHandy[3] = (int) Math.round(0.7*r);
       for (int i = 0; i<12; i++) {
           t = -2.0*Math.PI*((double) i)/12.0;
           si = Math.sin(t);
           co = Math.cos(t);
           for (int j=0; j<4; j++) {
               drawHandx[j] = (int) Math.round( cx+ hourHandx[j]*co - hourHandy[j]*si);
               drawHandy[j] = (int) Math.round( cy- hourHandx[j]*si - hourHandy[j]*co);
            }
           g1.fillPolygon( drawHandx, drawHandy, 4);
        }
       
      // draw the minute-marks
       hourHandx[0] = (int) Math.round(0.015*r);
       hourHandy[0] = (int) Math.round(0.83*r);
       hourHandx[1] = (int) Math.round(0.015*r);
       hourHandy[1] = (int) Math.round(0.9*r);
       hourHandx[2] = (int) Math.round(-0.015*r);
       hourHandy[2] = (int) Math.round(0.9*r);
       hourHandx[3] = (int) Math.round(-0.015*r);
       hourHandy[3] = (int) Math.round(0.83*r);
       for (int i = 0; i<60; i++) {
           t = -2.0*Math.PI*((double) i)/60.0;
           si = Math.sin(t);
           co = Math.cos(t);
           for (int j=0; j<4; j++) {
               drawHandx[j] = (int) Math.round( cx+ hourHandx[j]*co - hourHandy[j]*si);
               drawHandy[j] = (int) Math.round( cy- hourHandx[j]*si - hourHandy[j]*co);
            }
           g1.fillPolygon( drawHandx, drawHandy, 4);
        }  
       
       // prepare the polygon for the hour-hand
       hourHandx[0] = (int) Math.round(0.045*r);
       hourHandy[0] = (int) Math.round(-0.15*r);
       hourHandx[1] = (int) Math.round(0.035*r);
       hourHandy[1] = (int) Math.round(0.6*r);
       hourHandx[2] = (int) Math.round(-0.035*r);
       hourHandy[2] = (int) Math.round(0.6*r);
       hourHandx[3] = (int) Math.round(-0.045*r);
       hourHandy[3] = (int) Math.round(-0.15*r);
       
        // prepare the polygon for the minute-hand
       minHandx[0] = (int) Math.round(0.035*r);
       minHandy[0] = (int) Math.round(-0.15*r);
       minHandx[1] = (int) Math.round(0.03*r);
       minHandy[1] = (int) Math.round(0.85*r);
       minHandx[2] = (int) Math.round(-0.03*r);
       minHandy[2] = (int) Math.round(0.85*r);
       minHandx[3] = (int) Math.round(-0.035*r);
       minHandy[3] = (int) Math.round(-0.15*r);
       
       // prepare the polygon for the seconds-hand
       secHandx[0] = (int) Math.round(0.015*r);
       secHandy[0] = (int) Math.round(-0.2*r);
       secHandx[1] = (int) Math.round(0.015*r);
       secHandy[1] = (int) Math.round(0.6*r);
       secHandx[2] = (int) Math.round(-0.015*r);
       secHandy[2] = (int) Math.round(0.6*r);
       secHandx[3] = (int) Math.round(-0.015*r);
       secHandy[3] = (int) Math.round(-0.2*r);
        
        thread= new Thread(this); // thread is a new thrad of this applet
        thread.start(); // start the thread
       
    }  
 
    public void destroy()
    {
        thread = null; // set thread to zero if applet is stopped
    } 
 
    public void run()
     {
          while (true) // endless loop
          {    
            Calendar cal = new GregorianCalendar();  // date and time now!
            // Get the components of the time
            //int hour12 = cal.get(Calendar.HOUR);            // 0..11
            //int hour24 = cal.get(Calendar.HOUR_OF_DAY);     // 0..23
            //int min = cal.get(Calendar.MINUTE);             // 0..59
            //int sec = cal.get(Calendar.SECOND);             // 0..59
            //int ms = cal.get(Calendar.MILLISECOND);         // 0..999
            //int ampm = cal.get(Calendar.AM_PM);             // 0=AM, 1=PM
        
            // draw the clock without the hands
            g2.drawImage( BuffImage1, 0, 0, null); 
       
            // draw the hours-hand
            g2.setColor(Color.black);
            t = -2.0*Math.PI*((double) cal.get(Calendar.HOUR))/12.0;
            t = t + -2.0*Math.PI*((double) cal.get(Calendar.MINUTE))/60.0/12.0;
            si = Math.sin(t);
            co = Math.cos(t);
            for (int j=0; j<4; j++) {
                drawHandx[j] = (int) Math.round( cx+ hourHandx[j]*co - hourHandy[j]*si);
                drawHandy[j] = (int) Math.round( cy- hourHandx[j]*si - hourHandy[j]*co);
            }
            g2.fillPolygon( drawHandx, drawHandy, 4);
       
            // draw the minutes-hand
            t = -2.0*Math.PI*((double) cal.get(Calendar.MINUTE))/60.0;
            si = Math.sin(t);
            co = Math.cos(t);
            for (int j=0; j<4; j++) {
                drawHandx[j] = (int) Math.round( cx+ minHandx[j]*co - minHandy[j]*si);
                drawHandy[j] = (int) Math.round( cy- minHandx[j]*si - minHandy[j]*co);
            }
            g2.fillPolygon( drawHandx, drawHandy, 4);
       
            // draw the seconds-hand
            g2.setColor(Color.red);
            t = (double) cal.get(Calendar.SECOND) + 0.001*cal.get(Calendar.MILLISECOND);
            t = 61.0*t/60.0;  // seconds-hand runs fast
            t = Math.min(t, 60.0);
            t = -2.0*Math.PI*t/60;
            si = Math.sin(t);
            co = Math.cos(t);
            for (int j=0; j<4; j++) {
                drawHandx[j] = (int) Math.round( cx+ secHandx[j]*co - secHandy[j]*si);
                drawHandy[j] = (int) Math.round( cy- secHandx[j]*si - secHandy[j]*co);
            }
            g2.fillPolygon( drawHandx, drawHandy, 4);
            g2.fillOval(  cx+(int) (-0.6*r*si - 0.1*r), cy-(int) (0.6*r*co + 0.1*r), (int) (0.2*r),  (int) (0.2*r) );
                    
            g2.setColor(Color.black);
            g2.fillOval( cx-(int) (0.01*r), cy-(int) (0.01*r), (int) (0.02*r), (int) (0.02*r));
              
               
              
              repaint(); // call paint() 
               try // try to wait 40 milliseconds
               {
                   Thread.sleep(40);
               }
               catch (InterruptedException e) // if this did not word  
               {
                    System.out.println(e); // print the exception
               }
          }
 
     } 
 
   /** update()-method for applet
     *  (overridden to avoid flicker)
     *  @param g  the Grapics object for this applet
     */
    public void update( Graphics g )  {
        //display buffered image 
        g.drawImage( BuffImage2, 0, 0, null);
    } // end update()
     
    public void paint( Graphics g ) 
    {
       update(g);
    }  
    
}
