// Class   : Timer
// Author  : Russ Ethington
// Version : 1/28/96 for Java 1.0
// Notice  : Copyright (C) 1995, 1996 Russ Ethington

import java.lang.*;
import java.util.*;

public class Timer implements Runnable
{
   private Date startTime, stopTime;
   private Thread life = null;
   private int duration = 0;
   private int lastDuration = 0;
   private int pulse = 1000;
   private boolean repeat = false;
   private boolean running = false;
   private String name = "Timer";
   private TimerHandler handler = null;
   
   Timer() { }
   
   Timer(int howLong) { setDuration(howLong); }
   
   Timer(TimerHandler theHandler) { setHandler(theHandler); }
   
   Timer(int howLong, TimerHandler theHandler)
   {
      setDuration(howLong);
      setHandler(theHandler);
   }
    
   public void setDuration(int howLong) { duration = howLong; }
   
   public void setRepeat(boolean which) { repeat = which; }

   public void setHandler(TimerHandler theHandler) { handler = theHandler; }
   
   public void setPulse(int thePulse) { pulse = thePulse; }
   
   public void setName(String theName) { name = theName; }
   
   public int getDuration() { return duration; }

   public boolean getRepeat() { return repeat; }
   
   public TimerHandler getHandler() { return handler; }

   public int getPulse() { return pulse; }   
   
   public String getName() { return name; }

   public int getElapsed() { return computeElapsedTime(new Date()); }   

   public void resetDuration() { duration = lastDuration; }   
      
   public void start()
   {
      life = new Thread(this);
      life.start();
   }

   public void stop()
   {
      running = false;
      stopTime = new Date();
      if (handler != null)
         handler.timerStopped(this);
   }
   
   public void run()
   {
      running = true;
      lastDuration = duration;

      startTime = new Date();
      if (handler != null)
         handler.timerStarted(this);

      while (running)
      {
	 try {
            waitHere(pulse);
	 }
         catch (InterruptedException e) {
            return;
	 }
            
         if (handler != null)
            handler.timerPulse(this);
            
         if (duration > 0) // run indefinitely if duration not set
         {
            if (isExpired())
            {
               if (handler != null)
                  handler.timerExpired(this);               
               
               if (repeat)
               {
                  running = true;
                  startTime = new Date();
                  if (handler != null)
                     handler.timerStarted(this);   
               }
               else
               {
                  running = false;
               }
            }
         }
      }
   }    
   
   public boolean isRunning() { return running; }
   
   public boolean isStopped() { return !running; }
   
   public boolean isExpired()
   {
      int seconds = 0;

      seconds = computeElapsedTime(new Date());

      if (seconds >= duration) 
         return true;
      else
         return false;
   }
         
   private int computeElapsedTime(Date now)
   {
      Date endTime;
      int  seconds = 0;

      if (running)
         endTime = now;
      else
         endTime = stopTime;

      seconds += (endTime.getHours() - startTime.getHours()) * 3600;
      seconds += (endTime.getMinutes() - startTime.getMinutes()) * 60;
      seconds += (endTime.getSeconds() - startTime.getSeconds());
      return seconds;
   }
   
   private synchronized void waitHere(int delay) throws InterruptedException
   {
      this.wait(delay);
   }   
}
  


