/*
 * Clock.java 
 *
 * Copyright (c) 1997 H.J. Tsai, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. 
 *
 * H.J. Tsai MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE, OR NON-INFRINGEMENT. H.J. Tsai SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * Version 3.0a Feb 21, 1999	remove Thread's deprecated stop() method
 *
 * Version 3.0  Jan 8, 1997     Added support for timezone stuff
 *
 * Version 2.0  Nov 10, 1996 	Added abstract method tick()
 *
 * Version 1.0  Sep 8 1996      Initial version
 */

import java.applet.*;
import java.util.Date;

/**
 * An abstract base class for a clock. The derived classes should implement the
 * the tick() method and handle the GUI display. The tick() method is called
 * every second.
 */
public abstract class Clock extends Applet implements Runnable {
    // variables
    private int ss = -1;
    private int mm = -1;
    private int hh = -1;
    private int m = 0;
    private int h = 0;
    private int yr = 0;
    private int mo = 0;
    private int day = 0;
    private boolean forTimezone = false;
    private long    timezoneDiff = 0L;   // in milli seconds

    private Thread timer;
    
    public void init() {
        hh = mm = ss = -1;
        m = h = 0;
        timezoneDiff = 0L;
    }
    
    public void start() {
        if (timer == null) 				 
            timer = new Thread(this);
        
        timer.setPriority(Thread.MIN_PRIORITY);
        timer.start();
    }

    public void stop() {
        // if (timer != null) 
        // timer.stop();
        timer = null;
    }

    public void run() {

        setDisplayTime();

        while (timer != null) {
            try {
            
                Thread.sleep(250);
                
                Date d = new Date();
                
                if (d.getSeconds() != ss) {
                    ss = d.getSeconds();

                    if (d.getMinutes() != mm) {
                        mm = d.getMinutes();
                        hh = d.getHours();
                        setDisplayTime();
                    }
				
                    tick();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }

    protected int getDisplayHours() {
        return h;
    }

    protected int getDisplayMinutes() {
        return m;
    }

    protected int getDisplaySeconds() {
        return ss;
    }

    protected int getDisplayYear() {
        return yr;
    }

    protected int getDisplayMonth() {
        return mo;
    }

    protected int getDisplayDay() {
        return day;
    }

    /*
     * set the desired display time zone difference in
     * minutes from GMT (tzd)
     */ 
    protected void setTimezoneDiff(int tzd) {
        
        timezoneDiff = ((long) tzd) * 60L * 1000L;

        //System.err.println("desired GMT timeZoneOffset= " +  timezoneDiff);
        forTimezone = true;

        setDisplayTime();
    }


    protected void setDisplayTime() {
	
        Date now = new Date();
  	
        // tzlocal = the number of minutes must be added
        // to GMT time to get the local time
        long tzlocal = now.getTimezoneOffset() * 60L * 1000L;
//      System.err.println("tzlocal = " + tzlocal/60/1000);

        // gmtime = number of milliseconds since 1970 GMT
        // adjusted to allow TimezoneOffset added by the system
        // when Date() is called
        long gmtime = now.getTime(); 

        if (forTimezone) {
            gmtime += tzlocal;
		
            // construct a Date with milliseconds since
            // 1970 GMT--adjusted to the desired timezone 
            gmtime += timezoneDiff;
        }


        Date newdate = new Date(gmtime);

        // convert to server Time 
        m = newdate.getMinutes();
        h = newdate.getHours();

        yr = newdate.getYear();
        mo = newdate.getMonth();
        day = newdate.getDate();
    }


    /**
     * The tick() abstract method for subclass to implement
     */
    public abstract void tick();
}