package de.renew.logging.gui;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

import de.renew.engine.events.SimulationEvent;
import de.renew.simulatorontology.simulation.StepIdentifier;


/**
 * Stores the log events ({@link SimulationEvent}) for a single simulation step.
 *
 * @author Sven Offermann
 */
public class StepTrace {
    private Vector<SimulationEvent> _events = new Vector<>();
    private Set<StepTraceChangeListener> _listeners = Collections.synchronizedSet(new HashSet<>());
    private StepIdentifier _step;

    /**
     * Setter for the StepIdentifier
     * @param step the StepIdentifier
     */
    public StepTrace(StepIdentifier step) {
        this._step = step;
    }

    /**
     * Logs a SimulationEvent
     * @param event the SimulationEvent to be logged
     */
    public void log(SimulationEvent event) {
        if (!_events.contains(event)) {
            _events.add(event);
            fireStepTraceChanged();
        }
    }

    /**
     * Getter for all logged SimulationEvents
     * @return An Array containing all logged SimulationEvents
     */
    public SimulationEvent[] getEvents() {
        return this._events.toArray(new SimulationEvent[] { });
    }

    /**
     * Getter for the current StepIdentifier
     * @return the current StepIdentifier
     */
    public StepIdentifier getStepIdentifier() {
        return this._step;
    }

    @Override
    public String toString() {
        return "Simulator Step " + _step;
    }

    /**
     * Adds a StepTraceChangeListener
     * @param listener the StepTraceChangeListener to be added
     */
    public void addStepTraceChangeListener(StepTraceChangeListener listener) {
        this._listeners.add(listener);
    }

    /**
     * Removes a StepTraceChangeListener
     * @param listener the StepTraceChangeListener to be removed
     * @return true if the StepTraceChangeListener was removed,
     * false if the given StepTraceChangeListener wasn't added first
     */
    public boolean removeStepTraceChangeListener(StepTraceChangeListener listener) {
        //TODO change void?
        return this._listeners.remove(listener);
    }

    /**
     * Informs all StepTraceChangeListeners about a change in this StepTrace
     */
    public void fireStepTraceChanged() {
        StepTraceChangeListener[] l = this._listeners.toArray(new StepTraceChangeListener[] { });
        for (int x = 0; x < l.length; x++) {
            l[x].stepTraceChanged(this);
        }
    }
}