package de.renew.application;

import java.util.Collection;

import de.renew.engine.searcher.Searcher;
import de.renew.engine.simulator.ExecuteFinder;
import de.renew.engine.simulator.SimulatorHelper;
import de.renew.net.NetInstance;
import de.renew.net.NetInstanceList;
import de.renew.net.Transition;
import de.renew.net.TransitionInstance;
import de.renew.simulator.api.SimulationManager;
import de.renew.simulatorontology.simulation.StepIdentifier;


/**
 * Utility to access transition instances. Transitions marked "manual"
 * can be fired by providing the net instance id and the transition
 * name - usually given by a name annotation.
 * (Code has been taken from
 * <code>de.renew.agent.interactiontest.NetTestFramework</code>)
 *
 * @author cabac, stosch
 */
public class Util {
    /**
     * Creates a new <code>Util</code> instance. (Empty Constructor)
     */
    public Util() {}

    /**
     * Fires the given transition if found and fireable. Returns whether
     * transition was found.
     *
     * @param instance {@link NetInstance} where the given transition is located
     * @param name     the {@link Transition}'s name. Must exactly match the correct
     *                 name.
     * @return <code>true</code> if found, else <code>false</code>
     */
    public boolean fireTransition(NetInstance instance, String name) {
        Transition transition = findTransition(instance, name);
        if (transition == null) {
            return false;
        }
        TransitionInstance transitionInstance = instance.getInstance(transition);
        ExecuteFinder finder = new ExecuteFinder();
        Searcher searcher = new Searcher();
        SimulatorHelper.searchOnce(searcher, finder, transitionInstance, transitionInstance);

        if (finder.isCompleted()) {
            StepIdentifier step = SimulationManager.getCurrentSimulator().nextStepIdentifier();
            finder.execute(step, true);
        }
        return true;
    }

    /**
     * Returns a transition with the given name in the given NetInstance.
     *
     * @param instance {@link NetInstance} where the given transition is located
     * @param name     the {@link Transition}'s name. Must exactly match the correct
     *                 name.
     * @return transition if found, else <code>null</code>
     */
    private Transition findTransition(NetInstance instance, String name) {
        Collection<Transition> transitions = instance.getNet().transitions();
        Transition selection = null;
        for (Transition transition : transitions) {
            if (transition.getName().equals((name))) {
                selection = transition;
                break;
            }
        }
        return selection;
    }

    /**
     * Returns the net instance with the given name.
     *
     * @param netInstanceName the name of the net instance to find.
     * @return the net instance with the given name
     *         or <code>null</code> if no net instance could be found.
     */
    public NetInstance findInstance(String netInstanceName) {
        return NetInstanceList.getNetInstance(netInstanceName);

    }
}