package threads;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 *  This class provides a visual representation of the SteamBoiler.
 */
public class SteamBoilerApplet extends JApplet implements Runnable
{
  public void init()
  {
    m_gauge = new PressureGauge( new SteamBoiler() );
    setContentPane( createBoilerLayout() );
  }
  
  public void start()
  {
    m_timer = new Thread(this);
    m_timer.start();    // Start the timer
  }
  
  public void stop()
  {
    m_timer = null; // Stop the timer
  }
  
  private JPanel createBoilerLayout()
  {
    JPanel panel = new JPanel( new BorderLayout() );
    panel.setBackground(Color.lightGray);
    
    JLabel label = new JLabel("Steam Boiler (Max Pressure = " +
      SteamBoiler.PRESSURE_LIMIT + ")"
      );
    JPanel north = new JPanel( new FlowLayout(FlowLayout.CENTER) );
    north.add(label);
    panel.add(north, BorderLayout.NORTH);
    
    panel.add(m_gauge, BorderLayout.CENTER);
    
    JPanel south = new JPanel( new FlowLayout(FlowLayout.CENTER) );
    m_startButton.addActionListener( new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        m_startButton.setEnabled(false);
        m_gauge.getBoiler().start();   // Start the boiler
      }
    }
    );
    south.add(m_startButton);
    
    m_lastPressure = m_gauge.getPressure();
    m_pressureText = new JLabel(PRESSURE_TEXT + m_lastPressure);
    south.add(m_pressureText);
    
    m_resetButton.addActionListener( new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        m_gauge.setBoiler( new SteamBoiler() );
        m_startButton.setEnabled(true);
      }
    }
    );
    south.add(m_resetButton);
    panel.add(south, BorderLayout.SOUTH);
    
    return panel;
  }
  
  /**
   *   This constitutes a timer thread to refresh the gauge
   *   on a regular basis.
   */
  public void run()
  {
    while (m_timer != null)
    {
      try
      {
        Thread.sleep(100);
      }
      catch (InterruptedException e)
      {
        // Ignore
      }
      
      // Repaint if the pressure has changed since last time
      int pressure = m_gauge.getPressure();
      if (pressure != m_lastPressure)
      {
        m_lastPressure = pressure;
        m_pressureText.setText(PRESSURE_TEXT + pressure);
        m_gauge.repaint();
      }
    }
  }
  
  ///////// Private Data //////
  private boolean         m_laidOut = false;
  private Thread          m_timer;
  private PressureGauge   m_gauge;
  private JButton         m_startButton = new JButton("Burn!");
  private JButton         m_resetButton = new JButton("Reset");
  private JLabel          m_pressureText;
  private int             m_lastPressure = 0;
  
  private static final String PRESSURE_TEXT = "Pressure = ";
}

/**
 * Produces a 'thermometer' style gauge
 */
class PressureGauge extends JPanel
{
  public PressureGauge(SteamBoiler boiler)
  {
    setBoiler(boiler);
  }
  
  public void setBoiler(SteamBoiler boiler)
  {
    m_boiler = boiler;
    repaint();
  }
  
  public SteamBoiler getBoiler()
  {
    return m_boiler;
  }
  
  public int getPressure()
  {
    return m_boiler.getPressure();
  }
  
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    Dimension dim = getSize();
    int x = (dim.width - OUTER_WIDTH)/2;
    int y = 0;
    
    // Draw outer white area
    g.setColor(Color.WHITE);
    g.fillRect(x, y, OUTER_WIDTH, dim.height);
    
    // Draw the outline
    g.setColor(Color.black);
    int width = OUTER_WIDTH - INSET - INSET;
    int height = dim.height - INSET - INSET;
    g.drawRect(x + INSET - 1, y + INSET - 1, width + 1, height + 1);
    
    // Draw the "mercury"
    Color color = Color.blue;
    if (getPressure() > SteamBoiler.PRESSURE_LIMIT)
      color = Color.red;
    g.setColor(color);
    
    float factor = (float) getPressure() / (float) (SteamBoiler.PRESSURE_LIMIT * 10);
    height = (int) ((float)height * factor);
    g.fillRect(x + INSET, dim.height - height - INSET, width, height);
  }
  
  ///// Private data ///////
  private static final int OUTER_WIDTH = 20;
  private static final int INSET = 5;
  
  private SteamBoiler m_boiler;
}