/*
 *  GOLCellularAutomaton.
 *  Copyright (C) 2002  Frank Buß (fb@frank-buss.de)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You can get the GNU General Public License at
 *  http://www.gnu.org/licenses/gpl.html
 */

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/**
 * Game Of Life cellular automaton applet. Can be started as a normal
 * application as well.
 * 
 * @author Frank Buß
 */
public class GOLCellularAutomaton
	extends Applet
	implements Runnable, ActionListener {
	/**
	 * Used for applet title lable and Frame title.
	 */
	private final static String titleText =
		"Game Of Life Cellular Automaton V 1.0";

	/**
	 * Current animation.
	 */
	private Thread animation;

	/**
	 * Pauses the animation.
	 */
	private Button pauseButton;

	/**
	 * Starts and resumes the animation.
	 */
	private Button continueButton;

	/**
	 * Calculates and shows next CA step.
	 */
	private Button stepButton;

	/**
	 * Restarts the CA.
	 */
	private Button restartButton;

	/**
	 * Inits the CA with the rabbits pattern.
	 */
	private Button rabbitsButton;

	/**
	 * Inits the CA with the symmetric rabbits pattern.
	 */
	private Button symmetricRabbitsButton;

	/**
	 * CA model and view.
	 */
	private GOLCellularAutomatonCanvas automatonCanvas;

	/**
	 * If true, step will not be called for automatonCanvas. 
	 */
	private boolean pause = true;

	/**
	 * The animation thread runs until this is false.
	 */
	private boolean running = true;

	/**
	 * Starts the animation thread, but in paused state.
	 * @see java.applet.Applet#start()
	 */
	public void start() {
		if (animation == null) {
			animation = new Thread(this);
			animation.start();
		}
	}

	/**
	 * Stops the animation thread.
	 * @see java.applet.Applet#stop()
	 */
	public void stop() {
		running = false;
		animation = null;
	}

	/**
	 * If not paused, animates the automaton.
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		while (running) {
			if (pause) {
				try {
					Thread.sleep(100);
					automatonCanvas.repaint();
				} catch (Exception e) {
				}
			} else {
				automatonCanvas.step();
				automatonCanvas.repaint();
				try {
					Thread.sleep(10);
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * Creates GUI and starts the animation.
	 */
	public void init() {
		// create GUI
		setLayout(new BorderLayout());
		setBackground(Color.white);

		Panel inputContainer = new Panel();
		inputContainer.setLayout(new GridLayout(0, 1));

		pauseButton = new Button("Pause");
		inputContainer.add(pauseButton);
		pauseButton.addActionListener(this);

		continueButton = new Button("Animate / Continue");
		inputContainer.add(continueButton);
		continueButton.addActionListener(this);

		stepButton = new Button("Step");
		inputContainer.add(stepButton);
		stepButton.addActionListener(this);

		rabbitsButton = new Button("Rabbits");
		inputContainer.add(rabbitsButton);
		rabbitsButton.addActionListener(this);

		symmetricRabbitsButton = new Button("Symmetric Rabbits");
		inputContainer.add(symmetricRabbitsButton);
		symmetricRabbitsButton.addActionListener(this);

		restartButton = new Button("Random");
		inputContainer.add(restartButton);
		restartButton.addActionListener(this);

		inputContainer.add(new Label("© Frank Buß"));

		Panel p = new Panel(new BorderLayout());
		p.add(BorderLayout.NORTH, inputContainer);
		add(BorderLayout.WEST, p);

		automatonCanvas = new GOLCellularAutomatonCanvas();
		add(BorderLayout.CENTER, automatonCanvas);

		Label title = new Label(titleText, Label.CENTER);
		title.setFont(new Font("SansSerif", Font.PLAIN, 20));
		add(BorderLayout.NORTH, title);

		// start animation thread
		start();
	}

	/**
	 * Shows the applet in a AWT Frame.
	 * @param args Unused.
	 */
	public static void main(String args[]) {
		Frame f = new Frame(titleText);
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		f.setLayout(new BorderLayout());
		GOLCellularAutomaton a = new GOLCellularAutomaton();
		f.add(BorderLayout.CENTER, a);
		a.init();
		a.start();
		f.pack();
		f.setVisible(true);
	}

	/**
	 * Button actions.
	 * @see java.awt.event.ActionListener#actionPerformed(ActionEvent)
	 */
	public void actionPerformed(ActionEvent evt) {
		synchronized (automatonCanvas) {
			if (evt.getSource() == pauseButton) {
				pause = true;
			} else if (evt.getSource() == continueButton) {
				pause = false;
			} else if (evt.getSource() == stepButton) {
				automatonCanvas.step();
				automatonCanvas.repaint();
			} else if (evt.getSource() == restartButton) {
				automatonCanvas.init();
				automatonCanvas.repaint();
			} else if (evt.getSource() == rabbitsButton) {
				automatonCanvas.initRabbits();
				automatonCanvas.repaint();
			} else if (evt.getSource() == symmetricRabbitsButton) {
				automatonCanvas.initSymmetricRabbits();
				automatonCanvas.repaint();
			}
		}
	}
}
