package sim;

import java.awt.*;
import java.awt.event.*;

import sim.util.SimButton;
import sim.util.SimButtonListener;
import sim.util.StatusBox;
import sim.engine.*;

public class RunShortcut extends Panel {

	public static Thread PLAY_THREAD = null;
	public static GuiEngineLink LINK = null;
	private RunShortcutListener listener;

	public RunShortcut() {
		super();
		this.setLayout(new FlowLayout(FlowLayout.LEFT, 8, 0));
	}

	public void addNotify() {
		super.addNotify();
		this.listener = new RunShortcutListener(this);
	}

	/* ==================================================================
	 Services GuiEngineLink
	 ================================================================ */
	public void halt() {
		this.listener.halt();
	}
	/* ==================================================================
	 Services provided to Menu
	 ================================================================ */

	public void play() {
		this.listener.play();
	}

	public void stop() {
		this.listener.stop();
	}

	public void pause() {
		this.listener.pause();
	}

	public void timeStep() {
		this.listener.timeStep();
	}

	public void singleStep() {
		this.listener.singleStep();
	}

	/* ==================================================================
	 Listener to handle mouse events
	 ================================================================= */
	private class RunShortcutListener extends SimButtonListener {

		private SimButton play;
		private SimButton playSlow;
		private SimButton pause;
		private SimButton step;
		private SimButton stop;
		private boolean buttonUpOnLastMouseDown;
		private boolean started;
		private GuiEngineLink link;

		public RunShortcutListener(RunShortcut parent) {
			Panel p = new Panel(new FlowLayout(FlowLayout.LEFT, 0, 0));
			parent.add(p);

			this.buttonUpOnLastMouseDown = true;
			this.started = false;
			this.link = new GuiEngineLink();
			RunShortcut.LINK = this.link;

			this.stop = new SimButton("sim/images/Stop.png", "Stop", NorthPanel.BUBBLE_WAIT);
			this.stop.setListener(this);
			p.add(this.stop);

			this.play = new SimButton("sim/images/Play.png", "Start", NorthPanel.BUBBLE_WAIT);
			this.play.setListener(this);
			p.add(this.play);

			this.pause = new SimButton("sim/images/Pause.png", "Pause", NorthPanel.BUBBLE_WAIT);
			this.pause.setListener(this);
			p.add(this.pause);

			this.step = new SimButton("sim/images/Step.png", "Single step", NorthPanel.BUBBLE_WAIT);
			this.step.setListener(this);
			p.add(this.step);

			this.playSlow = new SimButton("sim/images/PlaySlow.png", "Time interval step", NorthPanel.BUBBLE_WAIT);
			this.playSlow.setListener(this);
			p.add(this.playSlow);

			this.stop.setEnabled(false);
			this.pause.setEnabled(false);
		}

		public void actionPerformed(ActionEvent e) {
			SimButton ib = (SimButton) e.getSource();
			if (ib == this.play) {
				this.play();
			} else if (ib == this.stop) {
				this.stop();
			} else if (ib == this.pause) {
				this.pause();
			} else if (ib == this.step) {
				this.singleStep();
			} else if (ib == this.playSlow) {
				this.timeStep();
			}
		}

		public void activate(SimButton ib) {
			ib.processActionEvent();
			ib.setArmed(false);
		}

		public void arm(SimButton ib) {
			ib.setArmed(true);
		}

		public void disarm(SimButton ib) {
			ib.setArmed(false);
		}

		public void mousePressed(MouseEvent event) {
			SimButton ib = (SimButton) event.getSource();
			if (ib.isEnabled()) {
				if (ib.isRaised()) {
					ib.paintInset();
					this.buttonUpOnLastMouseDown = ib.isRaised();
					this.arm(ib);
				}
			}
		}

		public void mouseClicked(MouseEvent event) {
			SimButton ib = (SimButton) event.getSource();
			if (ib.isEnabled() && ib.isArmed()) {
				this.activate(ib);
			}
		}

		public void mouseReleased(MouseEvent event) {
			SimButton ib = (SimButton) event.getSource();
			Point pt = event.getPoint();

			if (ib.contains(pt.x, pt.y)) {
				this.mouseClicked(event);
			}
		}

		public void mouseDragged(MouseEvent event) {
			SimButton ib = (SimButton) event.getSource();
			if (ib.isEnabled() && ib.isArmed()) {
				Point loc = event.getPoint();

				if (ib.contains(loc.x, loc.y)) {
					if (this.buttonUpOnLastMouseDown) {
						if (!ib.isRaised()) {
							ib.paintRaised();
						}
					} else if (ib.isRaised()) {
						ib.paintInset();
					}
				} else {
					if (this.buttonUpOnLastMouseDown) {
						if (ib.isRaised()) {
							ib.paintInset();
						}
					} else if (!ib.isRaised()) {
						ib.paintRaised();
					}
				}
			}
		}

		public void play() {
			if (this.play.isRaised()) {
				this.play.paintInset();
			}

			this.step.setEnabled(false);
			this.playSlow.setEnabled(false);

			if (!this.started) {
				this.started = true;

				this.stop.setEnabled(true);
				this.pause.setEnabled(true);

				SouthPanel.STATUS_BOX.setTitle("Simulating");
				this.link.setRealTime(0);
				MainWindow.WEST_PANEL.setEnabled(false);
				MainWindow.MENU.STOP.setEnabled(true);
				MainWindow.MENU.ATTRIBUTE.setEnabled(false);

				NorthPanel.STORE_SHORTCUT.setEnabled(false);
			} else {
				this.pause.paintRaised();
			}

			this.link.play();

			MainWindow.MENU.STEP.setEnabled(false);
			MainWindow.MENU.TIME_STEP.setEnabled(false);
			MainWindow.MENU.RUN.setEnabled(false);
			MainWindow.MENU.PAUSE.setEnabled(true);
		}

		public void stop() {
			this.started = false;
			this.stop.setEnabled(false);
			this.stop.paintRaised();

			if (this.play.isInset()) {
				this.play.paintRaised();
				this.pause.setEnabled(false);

				MainWindow.MENU.PAUSE.setEnabled(false);
				MainWindow.MENU.STEP.setEnabled(true);
				MainWindow.MENU.TIME_STEP.setEnabled(true);
				MainWindow.MENU.RUN.setEnabled(true);
			} else {
				this.pause.setEnabled(false);
				this.pause.paintRaised();
			}

			this.step.setEnabled(true);
			this.playSlow.setEnabled(true);

			this.link.stop();

			MainWindow.WEST_PANEL.setEnabled(true);
			MainWindow.MENU.STOP.setEnabled(false);
			MainWindow.MENU.ATTRIBUTE.setEnabled(true);

			NorthPanel.STORE_SHORTCUT.setEnabled(true);
		}

		public void pause() {
			if (this.pause.isRaised()) {
				this.pause.paintInset();
			}

			this.play.paintRaised();
			this.playSlow.setEnabled(true);
			this.step.setEnabled(true);
			this.link.pause();

			MainWindow.MENU.STEP.setEnabled(true);
			MainWindow.MENU.TIME_STEP.setEnabled(true);
			MainWindow.MENU.RUN.setEnabled(true);
			MainWindow.MENU.PAUSE.setEnabled(false);
		}

		public void timeStep() {
			this.playSlow.paintRaised();

			if (!this.started) {
				this.started = true;
				this.stop.setEnabled(true);
				this.pause.setEnabled(true);
				this.pause.paintInset();
				SouthPanel.STATUS_BOX.setTitle("Simulating");
				this.link.setRealTime(0);
				MainWindow.WEST_PANEL.setEnabled(false);
				MainWindow.MENU.STOP.setEnabled(true);
				MainWindow.MENU.ATTRIBUTE.setEnabled(false);

				NorthPanel.STORE_SHORTCUT.setEnabled(false);
			}

			this.link.slowPlay();
		}

		public void singleStep() {
			this.step.paintRaised();

			if (!this.started) {
				this.started = true;
				this.stop.setEnabled(true);
				this.pause.setEnabled(true);
				this.pause.paintInset();
				SouthPanel.STATUS_BOX.setTitle("Simulating");
				this.link.setRealTime(0);
				MainWindow.WEST_PANEL.setEnabled(false);
				MainWindow.MENU.STOP.setEnabled(true);
				MainWindow.MENU.ATTRIBUTE.setEnabled(false);

				NorthPanel.STORE_SHORTCUT.setEnabled(false);
			}

			this.link.step();
		}

		public void halt() {
			this.started = false;
			this.stop.setEnabled(false);
			this.stop.paintRaised();

			if (this.play.isInset()) {
				this.play.paintRaised();
				this.pause.setEnabled(false);

				MainWindow.MENU.PAUSE.setEnabled(false);
				MainWindow.MENU.STEP.setEnabled(true);
				MainWindow.MENU.TIME_STEP.setEnabled(true);
				MainWindow.MENU.RUN.setEnabled(true);
			} else {
				this.pause.setEnabled(false);
				this.pause.paintRaised();
			}

			this.step.setEnabled(true);
			this.playSlow.setEnabled(true);

			this.link.halt();
			MainWindow.WEST_PANEL.setEnabled(true);
			MainWindow.MENU.STOP.setEnabled(false);
			MainWindow.MENU.ATTRIBUTE.setEnabled(true);

			NorthPanel.STORE_SHORTCUT.setEnabled(true);
		}
	}
}
