package de.renew.net.inscription.arc;

import de.renew.engine.common.SimulatorEventLogger;
import de.renew.engine.events.QuicklyTesting;
import de.renew.engine.events.SimulationEvent;
import de.renew.engine.events.Testing;
import de.renew.engine.searcher.EarlyExecutable;
import de.renew.net.SimulatablePlaceInstance;
import de.renew.simulatorontology.simulation.StepIdentifier;
import de.renew.unify.Impossible;


class TestArcExecutable implements EarlyExecutable {
    private final SimulatablePlaceInstance _placeInstance;
    private final Object _token;
    private final boolean _trace;
    private final boolean _releaseImmediately;

    TestArcExecutable(
        SimulatablePlaceInstance placeInstance, Object token, boolean releaseImmediately,
        boolean trace)
    {
        _placeInstance = placeInstance;
        _token = token;
        _trace = trace;


        // If releaseImmediately is false, the tested token will remain
        // tested until it is explicitly untested.
        _releaseImmediately = releaseImmediately;
    }

    @Override
    public long lockPriority() {
        return _placeInstance.getLockOrder();
    }

    @Override
    public int phase() {
        return TEST;
    }

    /**
     * Locks the {@link de.renew.net.PlaceInstance#_lock PlaceInstance} associated with this arc.
     **/
    @Override
    public void lock() {
        _placeInstance._lock.lock();
    }

    @Override
    public void verify(StepIdentifier stepIdentifier) throws Impossible {
        _placeInstance.testToken(_token);
    }

    @Override
    public void execute(StepIdentifier stepIdentifier) {
        SimulationEvent event = _releaseImmediately ? new QuicklyTesting(_token, _placeInstance)
            : new Testing(_token, _placeInstance);

        if (_trace) {
            SimulatorEventLogger.log(stepIdentifier, event, _placeInstance);
        }

        if (_releaseImmediately) {
            _placeInstance.untestToken(_token);
        }
    }

    @Override
    public void rollback() {
        _placeInstance.untestToken(_token);
    }

    /**
     * Unlocks the {@link de.renew.net.PlaceInstance#_lock PlaceInstance} associated with this arc.
     **/
    @Override
    public void unlock() {
        _placeInstance._lock.unlock();
    }

    SimulatablePlaceInstance getPlaceInstance() {
        return _placeInstance;
    }

    Object getToken() {
        return _token;
    }

    boolean isTrace() {
        return _trace;
    }
}