package de.renew.simulatorontology.simulation;


/**
 * A simulator controls the search for and activation of
 * bindings.
 * <p>
 * Implementations that can represent multiple simulators must
 * offer a constructor that takes an integer and a boolean.
 * The integer gives the desired number of simulators and the
 * boolean specifies whether to realize an event queue delay.
 * {@code ParallelSimulator#ParallelSimulator(int, boolean)}
 * is an example.
 * Implementations that only represent a single simulator must
 * not offer a constructor that takes an integer and a boolean,
 * but instead a constructor that takes only the boolean.
 * {@code ConcurrentSimulator#ConcurrentSimulator(boolean)}
 * is an example.
 * Simulator objects are constructed by calling these constructors
 * in {@code de.renew.application.SimulatorPlugin#newSimulator}.
 * </p>
 * <p>
 * A simulator is part of the simulation facade. Therefore,
 * implementations should automatically switch to simulation
 * threads when appropriate: With exception of {@link #isActive()}
 * and {@link #isSequential()}, this applies to all methods declared
 * in this interface. The two methods that just query the state can
 * be called within any thread.
 * </p>
 * <p>
 * However, the constructor and any implementation-dependent code
 * of simulators may assume that it is executed within a simulation
 * thread.
 * </p>
 *
 * @author kummer
 *
 */
public interface Simulator {
    /**
     * The simulation was halted before I could determine
     * enabledness.
     **/
    int STATUS_STOPPED = 0;

    /**
     * The simulation of the step was completed.
     **/
    int STATUS_STEP_COMPLETE = 1;

    /**
     * The simulation of the step was completed.
     * There are no more enabled bindings.
     **/
    int STATUS_LAST_COMPLETE = 2;

    /**
     * There is no more enabled transition.
     **/
    int STATUS_CURRENTLY_DISABLED = 3;

    /**
     * There will never be an enabled transition.
     **/
    int STATUS_DISABLED = 4;

    /**
     * Return true, if the simulation could possibly
     * continue in the future.
     *
     * @return true if the simulation is active
     **/
    boolean isActive();

    /**
     * Start the simulation in the background.
     **/
    void startRun();

    /**
     * Gently stop the simulation.
     **/
    void stopRun();

    /**
     * Terminate the simulation once and for all.
     * Do some final clean-up and exit all threads.
     **/
    void terminateRun();

    /**
     * Perform just one more step. Return a status code according
     * to the five possibilities above.
     *
     * @return a status code according to the five status possibilities above
     **/
    int step();

    /**
     * Make sure to refresh internal data structures after the
     * firing of a transition outside the control of this simulator.
     * This is required by simulators that cache possible bindings.
     **/
    void refresh();

    /**
     * Tells whether the simulator operates in a strictly
     * sequential manner.
     *
     * @return true if the simulator operates in a strictly sequential manner
     **/
    boolean isSequential();

    /**
     * Returns the next simulation step identifier
     *
     * @return returns the next simulation {@link StepIdentifier}
     */
    StepIdentifier nextStepIdentifier();

    /**
     * Returns the current simulation step identifier
     *
     * @return returns the current simulation {@link StepIdentifier}
     */
    StepIdentifier currentStepIdentifier();

    /**
     * Collect all simulation run IDs of this simulator (all its aggregated
     * instances).
     *
     * @return the simulation run IDs of this simulator (all its aggregated instances)
     **/
    long[] collectSimulationRunIds();
}