// ==========================================================================
// $Id: StopWatch.java,v 1.1.1.1 2002/08/29 20:35:55 hitoshi Exp $
// a stopwatch 
// ==========================================================================
// Copyright (C) 2002 Yamauchi, Hitoshi
//
//   Max-Planck-Institut fuer Informatik AG4
//   Stuhlsatzenhausweg 85, 66123 Saarbruecken
//   http://www.mpi-sb.mpg.de/
// 
// This software can be redistributed only under GNU copyleft.
//
// @author Yamauchi Hitoshi »³Æâ ÀÆ
// ==========================================================================
// $Revision: 1.1.1.1 $
// $Date: 2002/08/29 20:35:55 $
// $Author: hitoshi $
// ==========================================================================
package de.mpg.mpisb.timerclock;

import  java.util.*;

/** 
 * a stopwatch 
 * This class has similer interface with the shared_proj of the MPI.
 */
public class StopWatch 
{
  /**
   * constructor
   */
  public StopWatch()
  {
    this.reset();
  }

  /**
   * run the stop watch. Error, if watch runs already. 
   */
  public void run()
  {
    if(this.mIsRuning)
    {
      throw new RuntimeException("StopWatch is already running");
    }
    this.mIsRuning  = true;
    this.mRunStartTime = (new Date()).getTime();
  }

  /**
   * stop the stop watch. Error, if watch stopped already. 
   */
  public void stop()
  {
    if(!(this.mIsRuning))
    {
      throw new RuntimeException("StopWatch is not running.");      
    }
    long runtime = (new Date()).getTime() - this.mRunStartTime;
    this.mAccumulateTime += runtime;
    this.mIsRuning = false;
  }

  /**
   * reset the watch.
   */
  public void reset()
  {
    this.mIsRuning 	 = false;
    this.mAccumulateTime = 0;    
    this.mRunStartTime   = 0;
  }

  /**
   * is running?
   */
  public synchronized boolean isRun()
  {
    return(this.mIsRuning);
  }
  
  /**
   * give the current (elapsed) time (in seconds); call only if watch is stopped.
   */
  public double time() 
  {
    if(this.mIsRuning)
    {
      throw new RuntimeException("StopWatch is still running.");      
    }
    double t = ((double)(this.mAccumulateTime)) * 0.001;
    return(t);
  }

  /**
   * peek the time. You can call at both running or stopping the watch.
   */
  public synchronized long peekTime()
  {
    if(this.mIsRuning)
    {
      // running
      long tmpruntime = (new Date()).getTime() - this.mRunStartTime;
      return(this.mAccumulateTime + tmpruntime);
    }
    else
    {
      // stopping
      return(this.mAccumulateTime);      
    }
  }

  /**
   * give the current (elapsed) time (in milliseconds); call only if watch is stopped.
   */
  public long elapsedMsec() 
  {
    if(this.mIsRuning)
    {
      throw new RuntimeException("StopWatch is still running.");      
    }
    return(this.mAccumulateTime);
  }

  /**
   * string representation
   */
  public String toString()
  {
    String r = "elapsed time = " + this.mAccumulateTime;
    return(r);
  }

  /**
   * the current global time with respect to some fix point in the past. 
   */
  public static double globTime()
  {
    double gt = (double)((new Date()).getTime()) * 0.001;    
    return(gt);
  }

  // private variables
  private boolean mIsRuning;
  private long    mAccumulateTime;
  private long    mRunStartTime;

  /*
   * main for test 
   */
  public static void main(String [] args)
  {
    StopWatch sw = new StopWatch(); 
    sw.run();
    try {
      Thread.sleep(1234);
    }catch (InterruptedException e)
    {
      System.out.println(e);
    }
    sw.stop();    
    System.out.println(sw);
  }
}
