package de.renew.net.inscription.transition;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import de.renew.engine.searcher.Binder;
import de.renew.engine.searcher.Executable;
import de.renew.engine.searcher.OccurrenceDescription;
import de.renew.engine.searcher.Searcher;
import de.renew.engine.searcher.VariableMapperCopier;
import de.renew.engine.thread.SimulationThreadPool;
import de.renew.expression.Expression;
import de.renew.expression.VariableMapper;
import de.renew.net.TransitionInstance;
import de.renew.net.inscription.AbstractOccurrence;
import de.renew.unify.Impossible;

/**
 * An occurrence of an action expression on a transition.
 */
class ActionOccurrence extends AbstractOccurrence {
    private final Expression _expression;
    private final VariableMapper _mapper;

    /**
     * Creates an {@link ActionOccurrence} and a {@link TransitionInstance} for a given {@code tInstance},
     * if the {@link SimulationThreadPool} is a {@link SimulationThread}.
     *
     * @param expression the {@link Expression} for this {@link ActionOccurrence}
     * @param mapper the {@link VariableMapper} for this {@link ActionOccurrence}
     * @param tInstance the {@link TransitionInstance}, which gets created
     */
    public ActionOccurrence(
        Expression expression, VariableMapper mapper, TransitionInstance tInstance)
    {
        super(tInstance);
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _expression = expression;
        _mapper = mapper;
    }

    @Override
    public Collection<Binder> makeBinders(Searcher searcher) throws Impossible {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        _expression.registerCalculation(
            _mapper, searcher.getStateRecorder(), searcher.getCalculationChecker());
        // That's it. No binders required.
        return Collections.emptySet();
    }

    @Override
    public Collection<Executable> makeExecutables(VariableMapperCopier copier) {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        List<Executable> executables = new ArrayList<>();
        executables.add(new ActionExecutable(_expression, copier.makeCopy(_mapper)));
        return executables;
    }

    @Override
    public OccurrenceDescription makeOccurrenceDescription(
        VariableMapperCopier variableMapperCopier)
    {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        return null;
    }
}