import java.awt.*;

// A clock to drive the CS100 real-time simulation environment. Its
// Frame displays the number of clock ticks thus far. It also displays
// the "period": the number of milliseconds that should appear between
// each clock tick. The user can change the period by typing in the
// TextField and pressing a button. periods less than 100 milliseconds
// are ignored.
public class SystemClock extends Frame implements Runnable {
// Constant defaultPeriod is the default period to sleep
  	public static final long defaultPeriod = 1000L;
  
private Thread me;          		// ID of this thread
private long counter= 0;       		// Current "time" on the clock
private long period= defaultPeriod; // Dleep interval

// Components for the Frame
	private Label clockLabel= new Label("Clock:       ");
	private Label periodLabel= new Label("Period is:    ");
	private TextField periodField= new TextField("");
	private Button button= new Button("Read period");

// Constructor: a clock whose period is set to the default
public SystemClock() {
	super("Clock");
	initialize(defaultPeriod);
  	}
  
// Constructor: a clock whose period is set to p
public SystemClock(long p) {
	super("Clock");
	initialize(p);
  	}
  	
// Initialize and show the Frame
private void initialize(long p) {
	period= p;
	reset();
	// Construct and show the Frame
		add("North", clockLabel);
		add("West", periodLabel);
		periodField.setText("" + period);
		add("East", periodField);
		add("South", button);
		resize(100,60);
    	pack();
    	move(5,100);
    	show();	
	}

// Set the clock to zero
public synchronized void reset() {
    counter = 0L;
    clockLabel.setText("Clock:   0");
  	}

// Return the current time on the clock (return -1 if
// the clock is not alive)
public synchronized long ticks()  {
    if (me != null && me.isAlive())
    	return counter;
    return -1L;
  	}
  
// Initiate execution of this thread. This method is invoked by method
// start() of class Thread to start execution of the thread.
public void run() {
    // Save the ID of this thread in me for future use 
    	me = Thread.currentThread();

    // Set the priority of this thread to the maximum allowed value
    	me.setPriority(Thread.MAX_PRIORITY);
    	
    // The following loop goes on forever. Each iteration puts
    // this thread to sleep for time period; when it wakes up, it
    // notifies waiting threads that it is awake and increments
    // the clock (by increasing counter)
    while(true) {
		try {me.sleep(period);}
		catch (InterruptedException ie)
			{System.err.println("System clock thread interrupted...");}

		// Notify all waiting threads, must hold lock to do so
		synchronized(this)
			{notifyAll();}

		// Increment "time"
			counter= counter + 1;
			clockLabel.setText("Clock: " + counter);
      	}
  	}
  	
// If a button was pressed, process it; otherwise, return
// result of super.action. The only button is "Read period".
public boolean action(Event e, Object arg) {
	if (arg.equals(button.getLabel())) {
		// Handle press of "Read period". If the requested period (in
		// periodField) is >= 100, then set period to it; otherwise,
		// set periodField back to what it was: period. Below, method
		// getText obtains the sequence of characters in component
		// periodField on the Frame; trim removes whitespace at either
		// end of the String, and parseInt converts it to an integer.
			String t= periodField.getText().trim();
			int p= Integer.parseInt(t);
			if (p < 100)
				periodField.setText("" + period);
			else period= p;
		return true;
		}
    return super.action(e, arg);
  	}
}

