package de.renew.net.inscription.transition;

import de.renew.engine.searcher.LateExecutable;
import de.renew.engine.thread.SimulationThreadPool;
import de.renew.expression.Expression;
import de.renew.expression.VariableMapper;
import de.renew.simulatorontology.simulation.StepIdentifier;
import de.renew.unify.Impossible;


class ActionExecutable implements LateExecutable {
    private final Expression _expression;
    private final VariableMapper _mapper;

    ActionExecutable(Expression expression, VariableMapper mapper) {
        _expression = expression;
        _mapper = mapper;
    }

    // Get the phase during which this executable should fire.
    @Override
    public int phase() {
        return ACTION;
    }

    // An action might take very long.
    @Override
    public boolean isLong() {
        return true;
    }

    // Execute this executable.
    @Override
    public void execute(StepIdentifier stepIdentifier) {
        assert SimulationThreadPool.isSimulationThread() : "is not in a simulation thread";
        try {
            // No undo past this point, so we may use null
            // as the current state recorder. Also, no
            // calculations should be registered with the checker.
            _expression.startEvaluation(_mapper, null, null);
        } catch (Impossible e) {
            // That hurts. Probably a method threw an exception.
            // This should have been caught by the compiler earlier on,
            // unless the error is a RuntimeException. So let's
            // be rigorous and throw a RuntimeException again.
            Throwable cause = e.getCause();
            if (cause == null) {
                cause = e;
            }
            throw new RuntimeException(
                "Action exception in step " + stepIdentifier + ": " + e.getMessage(), cause);
        }
    }

    @Override
    public void executeAfterException(StepIdentifier stepIdentifier, Throwable t) {}
}