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.gif", "Stop", NorthPanel.BUBBLE_WAIT);
			this.stop.setListener(this);
			p.add(this.stop);
			
			this.play = new SimButton("sim/images/Play.gif", "Start", NorthPanel.BUBBLE_WAIT);
			this.play.setListener(this);
			p.add(this.play);
			
			this.pause = new SimButton("sim/images/Pause.gif", "Pause", NorthPanel.BUBBLE_WAIT);
			this.pause.setListener(this);
			p.add(this.pause);
			
			this.step = new SimButton("sim/images/Step.gif", "Single step", NorthPanel.BUBBLE_WAIT);
			this.step.setListener(this);
			p.add(this.step);
			
			this.playSlow = new SimButton("sim/images/PlaySlow.gif", "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);
		}
	}
}
