import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;

public class TrafficBlink extends Applet
  implements ActionListener {

  private boolean runFlag;
  private Image img;
  private Graphics g;
  private Thread t = null;
  private int lightState;
  private Label titleLabel;
  private MyCanvas theCanvas; // defined below
  private BlinkLight blinkLight; // defined below
  private Button nextButton, blinkButton, stopButton;
  private Panel northPanel, centerPanel, southPanel;

  public void init () {

    lightState = 1;

    setLayout (new BorderLayout() );

    // north panel = title label

    northPanel = new Panel();
    northPanel.setLayout (new FlowLayout() );
    titleLabel = new Label ("Blinking Traffic Light Exercise ");
    northPanel.add(titleLabel);
    add (northPanel, "North");

    // center panel = traffic light drawing canvas

    theCanvas = new MyCanvas(); // defined below

    blinkLight = new BlinkLight(); // defined below

    centerPanel = new Panel();
    centerPanel.setLayout (new FlowLayout() );
    centerPanel.add(theCanvas);
    add (centerPanel, "Center");

    // south panel = buttons

    nextButton = new Button("Next");
    nextButton.addActionListener (this);
    nextButton.setActionCommand ("next");

    blinkButton = new Button("Blink");
    blinkButton.addActionListener (this);
    blinkButton.setActionCommand ("blink");

    stopButton = new Button("Stop");
    stopButton.addActionListener (this);
    stopButton.setActionCommand ("stop");

    southPanel = new Panel();
    southPanel.setLayout (new FlowLayout() );
    southPanel.add(nextButton);
    southPanel.add(blinkButton);
    southPanel.add(stopButton);
    add (southPanel, "South");

    // initial drawing

    setVisible(true);

    theCanvas.setSize(100,260);
    Dimension d = theCanvas.getSize();
    img = theCanvas.createImage(d.width, d.height);
    g=img.getGraphics();
    paintTraffic();
    theCanvas.repaint();
  }

  void paintTraffic () {
    switch (lightState) {
      case 1: paintLights (g, true, false, false); break;
      case 2: paintLights (g, true, true, false); break;
      case 3: paintLights (g, false, false, true); break;
      case 4: paintLights (g, false, true, false); break;
    }
  }

  void paintLights (Graphics g,
      boolean red, boolean yellow, boolean green) {
    g.setColor (Color.black);
    g.fillRect (10, 10, 80, 240);
    if (red) {
      g.setColor (Color.red);
      g.fillOval (20, 20, 60, 60);
    }
    if (yellow) {
      g.setColor (Color.yellow);
      g.fillOval (20, 100, 60, 60);
    }
    if (green) {
      g.setColor (Color.green);
      g.fillOval (20, 180, 60, 60);
    }
  }

  private class MyCanvas extends Canvas { // inner class

    public Dimension getMinimumSize() {
      return new Dimension(100,260);
    }
    public Dimension getPreferredSize() {
      return getMinimumSize();
    }

    public void paint (Graphics g) {
      update(g);
    }

    public void update (Graphics g) {
      if (img != null)
        g.drawImage(img,0,0,null); // no clear necessary
    }

  } // end of inner class MyCanvas

  private class BlinkLight implements Runnable { 
      // inner class
    public void run () {
      boolean onOff = false;
      runFlag = true;
      while (runFlag) {
        onOff = ! onOff;
        paintLights (g, false, onOff, false);
        theCanvas.repaint();
        // wait 1 second
        try { Thread.sleep(1000); }
        catch (InterruptedException e) {}
      }
    }
  } // end of inner class BlinkLight

  public void actionPerformed (ActionEvent e) {
    String which = (String) e.getActionCommand();
    if ( which.equals("next") ) {
      if (t != null) {
        t.stop();
        t=null;
      }
      lightState++;
      if (lightState>4)
        lightState=1;
      paintTraffic();
      theCanvas.repaint();
    }
    if ( which.equals("blink") ) {
      if (t == null) { // start blinking
        t = new Thread (blinkLight);
        t.start();
      }
      else { // end blinking
        t.stop();
        t=null;
        paintTraffic();
        theCanvas.repaint();
      }
    }
    if ( which.equals("stop") ) {
      if (t != null) {
        t.stop();
        t=null;
      }
      lightState=1;
      paintTraffic();
      theCanvas.repaint();
    }
  }

}

