// Simulation.java
package org.eclipse.stem.jobs.simulation;

/*******************************************************************************
 * Copyright (c) 2006, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.stem.core.Constants;
import org.eclipse.stem.core.CorePlugin;
import org.eclipse.stem.core.graph.GraphPartitioner;
import org.eclipse.stem.core.model.STEMTime;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.core.scenario.ScenarioInitializationException;
import org.eclipse.stem.core.scenario.impl.ScenarioImpl;
import org.eclipse.stem.core.scenario.provider.ScenarioItemProviderAdapterFactory;
import org.eclipse.stem.core.sequencer.Sequencer;
import org.eclipse.stem.core.solver.Solver;
import org.eclipse.stem.jobs.Activator;
import org.eclipse.stem.jobs.DisplaySafeExecutor;
import org.eclipse.stem.jobs.execution.Executable;
import org.eclipse.stem.jobs.preferences.PreferenceConstants;
import org.eclipse.stem.jobs.preferences.SimulationManagementPreferencePage;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

/**
 * This class implements the main simulation logic of the STEM system. It runs
 * in the background as a separate {@link Job} in eclipse.
 */
public class Simulation extends Executable implements ISimulation, IPropertyChangeListener {
	/**
	 * The collection of {@link ISimulationListener}'s waiting to be told about
	 * {@link Simulation}'s events.
	 */
	// I think this should really be a {@link CopyOnWriteArrayList} like {@link
	// #listenersSync}
	private final List<ISimulationListener> listeners = new CopyOnWriteArrayList<ISimulationListener>();
	/**
	 * The collection of {@link IBatchManagerListenerSync}'s waiting to be told
	 * about {@link BatchManagerEvent}'s
	 */
	private final List<ISimulationListenerSync> listenersSync = new CopyOnWriteArrayList<ISimulationListenerSync>();

	
	private final List<ISimulationListener> listenersHeadless = new CopyOnWriteArrayList<ISimulationListener>();

	private final List<ISimulationListenerSync> listenersSyncHeadless = new CopyOnWriteArrayList<ISimulationListenerSync>();

	
	
	
	/**
	 * If <code>true</code> then the {@link Simulation} will sleep for a
	 * specified time period at the end of each simulation cycle.
	 */
	public boolean simulationSleep = SimulationManagementPreferencePage.DEFAULT_SIMULATION_SLEEP;

	/**
	 * If {@link simulationSleep} is <code>true</code>, then this is the number
	 * of milliseconds at the end of each cycle that the {@link Simulation}
	 * should sleep.
	 */
	private int sleepMilliseconds = SimulationManagementPreferencePage.MIN_SIMULATION_SLEEP_MILLISECONDS;

	/**
	 * The current state of the {@link Simulation}.
	 */
	private SimulationState simulationState;

	/**
	 * This is the {@link Scenario} being simulated. It contains all of the
	 * {@link SimulationState} information.
	 */
	private Scenario scenario = null;

	private Adapter adapter = null; 

	private GraphPartitioner partitioner;
	
	/**
	 * This flag controls the execution of the {@link Simulation}. If it is
	 * <code>false</code> the {@link Simulation} stops running (sleeps) on the
	 * next cycle.
	 * 
	 * @see #pause()
	 */
	private boolean keepRunning = true;

	/**
	 * This flag controls the state of the {@link Simulation}. If
	 * <code>true</code> then the {@link Simulation} is stopped if it is running
	 * and the {@link Scenario} is reset to its initial state. The
	 * {@link Simulation} does NOT resume running after the reset.
	 * 
	 * @see #resetSimulation()
	 */
	private boolean reset = false;

	/**
	 * This flag indicates that the {@link Simulation} should complete a single
	 * step (cycle) and then pause.
	 */
	private boolean stepping = false;

	/**
	 * If <code>true</code> then the {@link Simulation} is stopping
	 */
	private boolean stopping = false;

	ScenarioItemProviderAdapterFactory scenarioItemProviderAdapterFactory = new ScenarioItemProviderAdapterFactory();
	/**
	 * Constructor
	 * 
	 * @param title
	 *            the title of the {@link Simulation}.
	 * @param sequenceNumber
	 *            the sequence number of the {@link Simulation}
	 */
	public Simulation(final String title, final int sequenceNumber) {
		super(title == null ? "" : title, sequenceNumber); //$NON-NLS-1$
		simulationState = SimulationState.PAUSED;
	} // Simulation

	/**
	 * Constructor
	 * 
	 * @param scenario
	 *            the {@link Scenario} to simulate
	 * @param sequenceNumber
	 *            the sequence number of the {@link Simulation}
	 */
	public Simulation(final Scenario scenario, final int sequenceNumber, GraphPartitioner p) {
		this(scenario.produceTitle(), sequenceNumber);
		this.scenario = scenario;
		this.partitioner = p;
		setPreferences();

		Activator.getDefault().getPluginPreferences().addPropertyChangeListener(this);
	} // Simulation

	/**
	 * Set the preferences.
	 * 
	 * @see #simulationSleep
	 * @see #sleepMilliseconds
	 */
	protected void setPreferences() {
		final Preferences preferences = Activator.getDefault()
		.getPluginPreferences();
		simulationSleep = preferences
		.getBoolean(PreferenceConstants.SIMULATION_SLEEP_BOOLEAN);
		sleepMilliseconds = preferences
		.getInt(PreferenceConstants.SIMULATION_SLEEP_MILLISECONDS_INTEGER);
		ScenarioImpl.reportEachUnresolvedIdentifiable = preferences
		.getBoolean(PreferenceConstants.REPORT_EACH_UNRESOLVED_IDENTIFIABLE_BOOLEAN);
		ScenarioImpl.reportDanglingAirTransportEdges = preferences
		.getBoolean(PreferenceConstants.REPORT_DANGLING_AIR_TRANPORT_EDGES_BOOLEAN);

		ScenarioImpl.reportNumberofUnresolvedIdentifiables = preferences
		.getBoolean(PreferenceConstants.REPORT_NUMBER_OF_UNRESOLVED_IDENTIFIABLES_BOOLEAN);

	} // setPerferences

	/**
	 * @return the state of the {@link Simulation}
	 */
	public final SimulationState getSimulationState() {
		return simulationState;
	} // getSimulationState

	/**
	 * @param simulationState
	 *            the {@link SimulationState} to set
	 */
	private final void setSimulationState(final SimulationState simulationState) {
		this.simulationState = simulationState;
		fireSimulationChanged(simulationState);
	} // setSimulationState

	boolean firstStep = true;
	
	/**
	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	protected IStatus run(final IProgressMonitor monitor) {
		IStatus retValue = Status.OK_STATUS;

		try {
			setSimulationState(SimulationState.RUNNING);

			keepRunning = true;

			// Did we get a request to reset?
			if (reset) {
				// Yes
				scenario.reset();
				reset = false;
			}

			assert scenario.sane();

			monitor.beginTask(scenario.produceTitle(), TOTAL_WORK);
			final Sequencer sequencer = scenario.getSequencer();

			// Figure out how much work has been performed for this scenario
			// already.
			// $ANALYSIS-IGNORE
			monitor.worked((int) sequencer.getWorkComplete());
			final Simulation self = this;
/*			adapter = new AdapterImpl() {
				@Override
				public void notifyChanged(Notification msg)
				{
					Scenario scenario = (Scenario)msg.getNotifier();
					switch(msg.getFeatureID(Scenario.class)) {
					case ScenarioPackage.SCENARIO__PROGRESS:
						SimulationEvent event = new SimulationEvent(self, SimulationState.RUNNING, scenario.getProgress());
						self.fireSimulationChangedEvent(event);
						break;
					}

				}
			}; 
			
			scenario.eAdapters().add(adapter);
			*/

			//ScenarioItemProvider sip = (ScenarioItemProvider)scenarioItemProviderAdapterFactory.adapt(this, ScenarioItemProvider.class);

			//scenarioItemProviderAdapterFactory.addListener(this); // ugh

			// Does the sequencer say we've finished before we've started?
			
			if (!sequencer.isTimeToStop()) {
				// No
				while (keepRunning && !reset) {
					final STEMTime currentTime = sequencer.getCurrentTime();
					monitor.subTask(currentTime.toString());

					// Attempt one step (cycle) in the simulation
						if(scenario.getCanonicalGraph() == null)
							scenario.initialize();

						if(scenario.getSolver() == null) {
							Solver [] solvers = this.getSolvers();
							// Use the default finite difference when not available
							for(Solver s:solvers)
								if(s.getClass().getName().equals("org.eclipse.stem.solvers.fd.impl.FiniteDifferenceImpl"))
								{scenario.setSolver(s);break;}

						}
						// Make sure the decorators are set on the solver
						scenario.getSolver().setCanonicalGraph(scenario.getCanonicalGraph());

						if(firstStep) {
							scenario.getSolver().initialize(scenario.getSequencer().getNextTime(), partitioner);
							setSimulationState(SimulationState.COMPLETED_CYCLE); // So that log is written with initial values
							firstStep = false;
						}

						boolean success = scenario.step();
						if(!success) {keepRunning = false;retValue = Status.CANCEL_STATUS;}
						assert scenario.sane();

						// To sleep, per chance to dream?
						if (simulationSleep) {
							// Yes
							try {
								Thread.sleep(sleepMilliseconds);
							} catch(InterruptedException ie) {
								ie.printStackTrace(); // Unlikley
							}
						}

						monitor.worked(sequencer.getWorkIncrement());

						// We stop when the sequencer tells us it is time
						if (sequencer.isTimeToStop()) {
							keepRunning = false;
							retValue = Status.OK_STATUS;
						}
						// Or, if things are canceled
						else if (monitor.isCanceled()) {
							keepRunning = false;
							retValue = Status.CANCEL_STATUS;
						}
						// Or, if we're stepping
						else if (stepping) {
							keepRunning = false;
						}

					setSimulationState(SimulationState.COMPLETED_CYCLE);
				} // while keepRunning

				// Was it time to stop?
				if (sequencer.isTimeToStop() && retValue == Status.OK_STATUS) {
					// Yes
					setSimulationState(SimulationState.COMPLETED_SEQUENCE);
				}
			} // if NOT time to stop before we start
			else {
				// Yes
				// The sequencer says we've finished before we started
				Activator.logInformation(MessageFormat.format(Messages
						.getString("Sim.Time_Error"), sequencer
						.getCurrentTime().toString(), sequencer.getEndTime()
						.toString()), null);
			} // else

			// Did we get a request to reset?
			if (reset) {
				// Yes
				scenario.reset();
				reset = false;
				setSimulationState(SimulationState.RESET);
			}

			monitor.done();

		} catch (final ScenarioInitializationException sie) {
			// Problem. We're out of here.
			handleException(sie, true);
			keepRunning = false;
			stopping = true;
		} // catch RuntimeException

		// Are we stopping or just pausing?
		setSimulationState(stopping ? SimulationState.STOPPED
				: SimulationState.PAUSED);

		return retValue;

	} // run

	

	/**
	 * Start running the {@link Simulation}.
	 */
	public final void run() {
		stepping = false;
		schedule();
	} // run

	/**
	 * Pause the {@link Simulation}
	 */
	public final void pause() {
		keepRunning = false;
	} // pause

	/**
	 * Reset the {@link Simulation}.
	 */
	public final void reset() throws ScenarioInitializationException {
		reset = true;
		stepping = false;
		// Is the simulation currently paused?
		if (getSimulationState().equals(SimulationState.PAUSED)) {
			// Yes
			scenario.reset();
			reset = false;
			setSimulationState(SimulationState.RESET);
			setSimulationState(SimulationState.PAUSED);
		} // if
	} // reset

	/**
	 * Step the {@link Simulation} one step/cycle if it hasn't already ended
	 */
	public final void step() {
		stepping = true;
		schedule();
	} // stepSimulation

	/**
	 * Stop the {@link Simulation}.
	 */
	public final void stop() {
		stopping = true;
		keepRunning = false;
		// We need to set our state here, which will notify our listeners,
		// because we may not be scheduled and so the run(IProgressMonitor)
		// method may not be executing and so would not set the state to STOPPED
		// (and thus notify listeners)
		setSimulationState(SimulationState.STOPPED);
	} // stepSimulation

	/**
	 * @see org.eclipse.stem.jobs.execution.IExecutable#isRunning()
	 */
	public boolean isRunning() {
		return !simulationState.equals(SimulationState.PAUSED);
	}

	/**
	 * @return the {@link Scenario}
	 */
	public final Scenario getScenario() {
		return this.scenario;
	}

	/**
	 * @param scenario
	 *            the {@link Scenario} to set
	 */
	protected final void setScenario(final Scenario scenario) {
		this.scenario = scenario;
	}

	/**
	 * @see org.eclipse.stem.jobs.simulation.ISimulation#addSimulationListener(org.eclipse.stem.jobs.simulation.ISimulationListener)
	 */
	public void addSimulationListener(final ISimulationListener listener) {
		addSimulationListener(listener, false);
	} // addSimulationListener

	public void addSimulationListener(final ISimulationListener listener, final boolean headlessSafe) {
		if (headlessSafe) {
			if (!listenersHeadless.contains(listener)) {
				listenersHeadless.add(listener);
			}
			
		} else {
			if (!listeners.contains(listener)) {
				listeners.add(listener);
			}
		}
	}

	public void addSimulationListenerSync(final ISimulationListenerSync listener, final boolean headlessSafe) {
		if (headlessSafe) {
			if (!listenersSyncHeadless.contains(listener)) {
				listenersSyncHeadless.add(listener);
			}
			
		} else {
			if (!listenersSync.contains(listener)) {
				listenersSync.add(listener);
			}
		}
		
	}
	
	
	/**
	 * @see org.eclipse.stem.jobs.simulation.ISimulation#addSimulationListenerSync(org.eclipse.stem.jobs.simulation.ISimulationListenerSync)
	 */
	public void addSimulationListenerSync(final ISimulationListenerSync listener) {
		addSimulationListenerSync(listener, false);
	} // addSimulationListenerSync

	/**
	 * @see org.eclipse.stem.jobs.simulation.ISimulation#removeSimulationListener(org.eclipse.stem.jobs.simulation.ISimulationListener)
	 */
	public void removeSimulationListener(final ISimulationListener listener) {
		listeners.remove(listener);
		listenersHeadless.remove(listener);
	} // removeSimulationListener

	/**
	 * @see org.eclipse.stem.jobs.simulation.ISimulation#removeSimulationListenerSync(org.eclipse.stem.jobs.simulation.ISimulationListenerSync)
	 */
	public void removeSimulationListenerSync(
			final ISimulationListenerSync listener) {
		listenersSync.remove(listener);
		listenersSyncHeadless.remove(listener);
	} // removeSimulationListenerSync

	/**
	 * Tell the listeners about the change in the {@link Simulation}'s state
	 * 
	 * @param simulationState
	 *            the new {@link SimulationState} of the {@link Simulation}
	 */
	private void fireSimulationChanged(final SimulationState simulationState) {
		final SimulationEvent event = new SimulationEvent(this, simulationState);
		fireSimulationChangedEvent(event);
	} // fireSimulationManagerChanged

	/**
	 * Tell the listeners about the change in the {@link Simulation}'s state
	 * 
	 * @param simulationState
	 *            the new {@link SimulationState} of the {@link Simulation}
	 */
	void fireSimulationChangedEvent(final SimulationEvent event) 
	{
		for (final ISimulationListener listener : listeners) {
			executeAsyncEvent(listener, event, false);
		} // for
		
		for (final ISimulationListener listener : listenersHeadless) {
			executeAsyncEvent(listener, event, true);
		} // for
		
		for (final ISimulationListenerSync listener : listenersSync) {
			executeSyncEvent(listener, event, false);
		} // for
		
		for (final ISimulationListenerSync listener : listenersSyncHeadless) {
			executeSyncEvent(listener, event, true);
		} // for


	} // fireSimulationManagerChanged
	
	
	/**
	 * @param listener
	 * @param event
	 * @param headlessSafe
	 */
	private void executeAsyncEvent(final ISimulationListener listener, final SimulationEvent event, final boolean headlessSafe)
	{
		DisplaySafeExecutor.executeAsync(new Runnable() {
			public void run()
			{
				listener.simulationChanged(event);
			}
		}, headlessSafe);
	}
	
	/**
	 * @param listener
	 * @param event
	 * @param headlessSafe
	 */
	private void executeSyncEvent(final ISimulationListenerSync listener, final SimulationEvent event, final boolean headlessSafe)
	{
		DisplaySafeExecutor.executeSync(new Runnable() {
			public void run()
			{
				listener.simulationChangedSync(event);
			}
		}, headlessSafe);
	}
	
	

	/**
	 * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
	 */
	public void propertyChange(@SuppressWarnings("unused") final PropertyChangeEvent event) {
		setPreferences();
	} // propertyChange

	/**
	 * @return the title of the {@link Scenario}
	 */
	@Override
	public String toString() {
		return scenario.produceTitle();
	}

	/**
	 * interruptRequested. Return true if this listener requests 
	 * that a decorator stops updating labels
	 * 
	 * @return boolean True if stop
	 */

	public boolean interruptRequested() {
		return (!this.keepRunning && stopping);
	}

	public void destroy() {
		List<ISimulationListener> tempList = new ArrayList<ISimulationListener>();
		tempList.addAll(listeners);
		for (ISimulationListener listener:tempList) {
			this.removeSimulationListener(listener);
		}
		listeners.clear();
		List<ISimulationListenerSync> tempListSync = new ArrayList<ISimulationListenerSync>();
		tempListSync.addAll(listenersSync);
		for (ISimulationListenerSync listener:tempListSync) {
			this.removeSimulationListenerSync(listener);
		}
		listenersSync.clear();
		tempList.clear();
		tempListSync.clear();

		scenario.eAdapters().remove(adapter);

		Activator.getDefault().getPluginPreferences().removePropertyChangeListener(this);
	}

	private org.eclipse.stem.core.solver.Solver [] getSolvers() {
		Solver [] solvers;
		final IExtensionRegistry registry = Platform.getExtensionRegistry();
		final IConfigurationElement[] solverConfigElements = registry
		.getConfigurationElementsFor(org.eclipse.stem.core.Constants.ID_SOLVER_EXTENSION_POINT);

		final List<Solver> temp = new ArrayList<Solver>();

		//solvers = new Solver[solverConfigElements.length];

		for (int i = 0; i < solverConfigElements.length; i++) {
			final IConfigurationElement element = solverConfigElements[i];
			// Does the element specify the class of the disease model?
			if (element.getName().equals(Constants.SOLVER_ELEMENT)) {
				// Yes
				try {
					temp.add((Solver) element
							.createExecutableExtension("class")); //$NON-NLS-1$
				} catch (final Exception e) {
					CorePlugin.logError(
							"Can't create solver", e); //$NON-NLS-1$
				}
			} // if
		} // for each configuration element

		solvers = temp.toArray(new Solver[] {});

		return solvers;
	}


	/**
	 * Do the processing required to handle a {@link Exception}
	 * 
	 * @param scenario
	 *            the {@link Scenario} that caused the {@link Exception}
	 * @param name
	 *            the name to use in error messages that identifies the source
	 *            of the {@link Scenario}
	 * @param promptUser
	 *            if <code>true</code> then present the user with a dialog box
	 *            explaining the message.
	 * @param e
	 *            the {@link Exception}
	 */
	static public void handleException(final ScenarioInitializationException se,
			final boolean promptUser) {


		Activator.logError(se.getErrorMessage(), se.getOriginalException());

		// Prompt the user?
		if (promptUser) {
			// Yes
			try {
				Display d = DisplaySafeExecutor.safeGetDefaultDisplay();
				if (d != null) {
					d.syncExec(new Runnable() {
						public void run() {
							try {
								final IWorkbenchWindow window = PlatformUI
								.getWorkbench().getActiveWorkbenchWindow();
								final IStatus warning = new Status(IStatus.WARNING,
										Activator.PLUGIN_ID, 1, se.getErrorMessage(), null);
								ErrorDialog.openError(window.getShell(), null, null,
										warning);
							} catch(Exception e) {
								// If we get this exception, it is because we're not running in
								// eclipse.
							}
						} // run
					});
				}
			} catch (final Error ncdfe) {
				// Empty
			} // catch
		} // if
	} // handleRuntimeException
	
} // Simulation
