
import java.applet.Applet;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Point;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Color;

import java.util.Vector;

import java.net.URL;
import java.net.MalformedURLException;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.File;



public class MessageDisplayer extends Applet implements Runnable {

  public void init () {
    schedule = new Thread (this);
    clipRect = new Rectangle ();
    stringPoint = new Point ();
    currentString = "";
    messages = new Vector ();

    Font f = getFont ();
    setFont (new Font (f.getName (), f.getStyle () + Font.BOLD, f.getSize () + 4));

    setForeground (Color.white);

    URL sourceURL = getSourceURL ();
    loadBackgroundImage (sourceURL);
    loadMessages (sourceURL);
  }

  public void start () {
    if (schedule.isAlive ()) {
      schedule.resume ();
    }
    else {
      schedule.start ();
    }
  }

  public void stop () {
    schedule.suspend ();
  }

  public void destroy () {
    schedule.stop ();
    schedule = null;
  }

  public void paint (Graphics g) {
    super.paint (g);
    if (background != null) {
      g.drawImage (background, 0, 0, this);
    }
    g.drawString (currentString, stringPoint.x, stringPoint.y);
  }

  public void run () {
    boolean showNow = true;
    int interruptTime;
    while (true) {
      if (showNow) {
        selectNextString ();
        repaint (clipRect.x, clipRect.y, clipRect.width, clipRect.height);
        interruptTime = SHOWING_TIME;
      }
      else {
        currentString = "";
        repaint (clipRect.x, clipRect.y, clipRect.width, clipRect.height);
        interruptTime = HIDING_TIME;
      }
      showNow = !showNow;
      try {
        Thread.sleep (interruptTime);
      }
      catch (InterruptedException e) {
        // Don't care about this
      }
    }
  }

  private void selectNextString () {
    currentString = (String) messages.elementAt (0);
    messages.removeElementAt (0);
    messages.addElement (currentString);

    FontMetrics metrics = getFontMetrics (getFont ());
    int fontHeight = metrics.getHeight ();
    int fontWidth = metrics.stringWidth (currentString);
    metrics = null;    
    Rectangle appletBounds = getBounds ();

    clipRect.width = fontWidth;
    clipRect.height = 2 * fontHeight;
    clipRect.x = stringPoint.x = appletBounds.x + ((appletBounds.width / 2) - (fontWidth / 2));
    stringPoint.y = appletBounds.y + ((appletBounds.height / 2) + (fontHeight / 2));
    clipRect.y = appletBounds.y + ((appletBounds.height / 2) - (fontHeight / 2));
  }

  private void loadBackgroundImage (URL sourceURL) {
    String imagePath = getParameter ("Image");
    if (imagePath == null) {
      return;
    }
    try {
      background = getImage (new URL (sourceURL, imagePath));
      Dimension appletSize = getSize ();
      background = background.getScaledInstance (appletSize.width, appletSize.height, Image.SCALE_DEFAULT);
    }
    catch (MalformedURLException e) {
      e.printStackTrace ();
    }
  }

  private void loadMessages (URL sourceURL) {
    String messagesPath = getParameter ("Messages");
    try {
      URL messagesURL = new URL (sourceURL, messagesPath);
      InputStream is = messagesURL.openStream ();
      InputStreamReader isr = new InputStreamReader (is);
      BufferedReader reader = new BufferedReader (isr);
      String message;
      while ((message = reader.readLine ()) != null) {
        messages.addElement (message);
      }
      reader.close ();
      isr.close ();
      is.close ();
    }
    catch (Exception e) {
      e.printStackTrace ();
    }
    if (messages.size () == 0) {
      messages.addElement ("Something is wrong here! Where are the messages????");
    }
  }

  private URL getSourceURL () {
    URL codeBase = getCodeBase ();
    String path = new File (codeBase.getFile ()).getPath ();
    URL result = null;
    try {
      result = new URL (codeBase.getProtocol () + "://" + path);
    }
    catch (MalformedURLException e) {
      e.printStackTrace ();
    }
    return result;
  }

  private static final int SHOWING_TIME = 2000;
  private static final int HIDING_TIME = 400;

  private Thread schedule;
  private Image background;
  private Vector messages;

  private String currentString;
  private Point stringPoint;
  private Rectangle clipRect;

}
