/*
 *  Automaton.java
 *  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.awt.*;
import java.applet.*;
import java.math.*;

public class Automaton extends Applet implements Runnable {
	Thread animation;

	private Checkbox squareCheckbox;
	private Checkbox hexagonCheckbox;
	private Checkbox square8Checkbox;
	private TextField ruleTextField;
	private TextField widthTextField;
	private Checkbox initPointCheckbox;
	private Button applyButton;
	private Button ruleButton;
	private Button pauseButton;
	private Button continueButton;
	private Button stepButton;
	private AutomatonCanvas automatonCanvas;
	private boolean ruleMode;
	private boolean pause;

	public void start() {
		if (animation == null) {
			animation = new Thread(this);
			animation.start();
		}
	}

	public void stop() {
		if (animation != null) {
			animation.stop();
			animation = null;
		}
	}

	public void run() {
		while (true) {
			if (ruleMode || pause) {
				try {
					animation.sleep(100);
				} catch (Exception e) {
				}
			} else {
				synchronized (automatonCanvas) {
					if (!ruleMode)
						automatonCanvas.step();
				}
				automatonCanvas.repaint();
				try {
					animation.sleep(10);
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * Create GUI.
	 */
	public void init() {
		setLayout(new BorderLayout());
		setBackground(Color.white);

		Panel inputContainer = new Panel();
		inputContainer.setLayout(new BorderLayout());
		Panel input = new Panel();
		input.setLayout(new GridLayout(0, 1));

		input.add(new Label("Grid geometry:"));
		Panel grid = new Panel();
		grid.setLayout(new GridLayout(1, 0));
		CheckboxGroup cbg = new CheckboxGroup();
		squareCheckbox = new Checkbox("squares", cbg, false);
		hexagonCheckbox = new Checkbox("hexagons", cbg, true);
		square8Checkbox = new Checkbox("squares with 8 neighbours", cbg, false);

		grid.add(squareCheckbox);
		grid.add(hexagonCheckbox);
		grid.add(square8Checkbox);
		input.add(grid);

		input.add(new Label("Rule:"));
		ruleTextField = new TextField("340282366920938463444927863362353692950", 156);
		input.add(ruleTextField);

		input.add(new Label("Width:"));
		widthTextField = new TextField("4", 3);
		input.add(widthTextField);

		initPointCheckbox = new Checkbox("initial point", true);
		input.add(initPointCheckbox);

		applyButton = new Button("Apply");
		input.add(applyButton);

		ruleButton = new Button("Enable / disable rule editor");
		input.add(ruleButton);

		pauseButton = new Button("Pause");
		input.add(pauseButton);

		continueButton = new Button("Continue");
		input.add(continueButton);

		stepButton = new Button("Step");
		input.add(stepButton);

		inputContainer.add(BorderLayout.NORTH, input);
		add(BorderLayout.SOUTH, inputContainer);

		automatonCanvas = new AutomatonCanvas(this);
		add(BorderLayout.CENTER, automatonCanvas);

		Label title =
			new Label("Cellular Automaton V 0.2, Copyright 2002-2005 by Frank Buß", Label.CENTER);
		title.setFont(new Font("SansSerif", Font.PLAIN, 20));
		add(BorderLayout.NORTH, title);

		// Animation starten
		start();
	}

	/**
	 * Apply new rule, if a button was pressed.
	 */
	public boolean action(Event evt, Object what) {
		synchronized (automatonCanvas) {
			automatonCanvas.setZoom(Integer.parseInt(widthTextField.getText()));
			if (evt.target == applyButton) {
				ruleMode = false;
				automatonCanvas.init();
			} else if (evt.target == ruleButton) {
				ruleMode = !ruleMode;
				automatonCanvas.init();
			} else if (evt.target == pauseButton) {
				pause = true;
			} else if (evt.target == continueButton) {
				pause = false;
			} else if (evt.target == stepButton) {
				automatonCanvas.step();
				automatonCanvas.repaint();
			}
		}
		return true;
	}

	//
	// Getter
	//

	public int getCornerCount() {
		if (squareCheckbox.getState())
			return 4;
		if (hexagonCheckbox.getState())
			return 6;
		if (square8Checkbox.getState())
			return 8;
		return 0;
	}

	public BigInteger getRule() {
		return new BigInteger(ruleTextField.getText());
	}

	public void setRule(BigInteger rule) {
		ruleTextField.setText(rule.toString());
	}

	public boolean isInitPoint() {
		return initPointCheckbox.getState();
	}

	public boolean isRuleMode() {
		return ruleMode;
	}

	public boolean isPaused() {
		return pause;
	}
}
