/*
 * Created on 17.08.2004
 */

package de.renew.engine.common;

import de.renew.application.SimulatorPlugin;
import de.renew.engine.events.SimulationEvent;
import de.renew.engine.thread.SimulationThreadPool;
import de.renew.net.NetInstance;
import de.renew.net.PlaceInstance;
import de.renew.net.TransitionInstance;
import de.renew.simulator.api.SimulationManager;
import de.renew.simulatorontology.simulation.StepIdentifier;


/**
 * Creates an event for the simulator with the possibility for a tracer {@link SimulationEvent}, {@link StepIdentifier},
 * {@link TransitionInstance} and {@link NetInstance}.
 *
 * @author Sven Offermann
 */
public class SimulatorEvent {
    private final StepIdentifier _stepIdentifier;
    private final SimulationEvent _logObject;
    private NetInstance _netInstance = null;

    // can be TransitionInstance, PlaceInstance or null
    private Object _netElementInstance = null;

    /**
     * Creates a new {@link SimulatorEvent} for a given {@link SimulationEvent}.
     * The current {@link StepIdentifier} of the current simulator is used.
     *
     * @param traceObject the {@link SimulationEvent} this event is about
     * @throws Exception if no simulator is running
     */
    public SimulatorEvent(SimulationEvent traceObject) throws Exception {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _logObject = traceObject;
        if (SimulatorPlugin.getCurrent() == null) {
            throw new Exception("No simulator running. Cant create Simulator Event.");
        }
        _stepIdentifier = SimulationManager.getCurrentSimulator().currentStepIdentifier();
    }

    /**
     * Creates a new {@link SimulatorEvent} for a given {@link StepIdentifier} and {@link SimulationEvent}.
     *
     * @param stepIdentifier the {@link StepIdentifier} this event is about
     * @param traceObject    the {@link SimulationEvent} this event is about
     */
    public SimulatorEvent(StepIdentifier stepIdentifier, SimulationEvent traceObject) {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _stepIdentifier = stepIdentifier;
        _logObject = traceObject;
    }

    /**
     * Creates a new {@link SimulatorEvent} for a given {@link StepIdentifier}, {@link SimulationEvent} and
     * {@link TransitionInstance}.
     *
     * @param stepIdentifier     the {@link StepIdentifier} this event is about
     * @param traceObject        the {@link SimulationEvent} this event is about
     * @param transitionInstance the {@link TransitionInstance} this event is about
     */
    public SimulatorEvent(
        StepIdentifier stepIdentifier, SimulationEvent traceObject,
        TransitionInstance transitionInstance)
    {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _stepIdentifier = stepIdentifier;
        _logObject = traceObject;
        _netElementInstance = transitionInstance;
        if (transitionInstance != null) {
            _netInstance = transitionInstance.getNetInstance();
        }
    }

    /**
     * Creates a new {@link SimulatorEvent} for a given {@link StepIdentifier}, {@link SimulationEvent} and
     * {@link PlaceInstance}.
     *
     * @param stepIdentifier the {@link StepIdentifier} this event is about
     * @param traceObject    the {@link SimulationEvent} this event is about
     * @param placeInstance  the {@link PlaceInstance} this event is about
     */
    public SimulatorEvent(
        StepIdentifier stepIdentifier, SimulationEvent traceObject, PlaceInstance placeInstance)
    {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _stepIdentifier = stepIdentifier;
        _logObject = traceObject;
        _netElementInstance = placeInstance;
        if (placeInstance != null) {
            _netInstance = placeInstance.getNetInstance();
        }
    }

    /**
     * Creates a new {@link SimulatorEvent} for a given {@link StepIdentifier}, {@link SimulationEvent} and
     * {@link NetInstance}.
     *
     * @param stepIdentifier the {@link StepIdentifier} this event is about
     * @param traceObject    the {@link SimulationEvent} this event is about
     * @param netInstance    the {@link NetInstance} this event is about
     */
    public SimulatorEvent(
        StepIdentifier stepIdentifier, SimulationEvent traceObject, NetInstance netInstance)
    {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _stepIdentifier = stepIdentifier;
        _logObject = traceObject;
        _netInstance = netInstance;
    }

    /**
     * Returns the {@link StepIdentifier} of the event.
     *
     * @return the step identifier
     */
    public StepIdentifier getStep() {
        return _stepIdentifier;
    }

    /**
     * Returns the log message.
     *
     * @return the log message
     */
    public SimulationEvent getMessage() {
        return _logObject;
    }

    @Override
    public String toString() {
        StringBuilder message = new StringBuilder();
        if (_stepIdentifier != null && _stepIdentifier.getComponents().length > 0) {
            message.append(_stepIdentifier);
        }
        message.append(_logObject.toString());
        return message.toString();
    }

    /**
     * Returns the net element instance (TransitionInstance or PlaceInstance) or null.
     *
     * @return the net element instance (TransitionInstance or PlaceInstance) or null
     */
    public Object getNetElementInstance() {
        return _netElementInstance;
    }

    /**
     * Returns the net instance or null.
     *
     * @return the net instance or null
     */
    public NetInstance getNetInstance() {
        return _netInstance;
    }
}