package de.renew.net.inscription.arc;

import java.util.Collection;

import de.renew.engine.searcher.TriggerableCollection;
import de.renew.net.SimulatablePlaceInstance;
import de.renew.net.inscription.transition.AssignBinder;
import de.renew.unify.Variable;

/**
 * An {@code ArcAssignBinder} is used to find tokens that belong to a {@link SimulatablePlaceInstance} and match a
 * {@code Variable} instance's value. When binding, a valid token is nondeterministically selected and unified with
 * the {@code Variable}. It is used by an {@link ArcOccurrence} to find and bind tokens from the connecting
 * {@code SimulatablePlaceInstance}, using the arc's evaluated {@link de.renew.expression.Expression} as
 * {@code Variable}. This is only advisable if the arc's expression is invertible.
 */
class ArcAssignBinder extends AssignBinder {
    /**
     * The place instance which the {@code ArcAssignBinder} checks for valid tokens.
     */
    private final SimulatablePlaceInstance _placeInstance;
    /**
     * {@code true}, if the corresponding {@code Arc} is a test arc or {@code false}, otherwise.
     */
    private final boolean _wantTest;

    /**
     * Creates a new {@code ArcAssignBinder} using the given values.
     *
     * @param variable the {@code Variable} whose value will be used to find matching tokens and that will be unified
     *                 with a matching token when {@link AssignBinder#bind} is called
     * @param placeInstance the place instance connected to the arc
     * @param wantTest {@code true}, if the arc is a test arc or {@code false}, otherwise
     */
    public ArcAssignBinder(
        Variable variable, SimulatablePlaceInstance placeInstance, boolean wantTest)
    {
        super(variable, false);
        _placeInstance = placeInstance;
        _wantTest = wantTest;
    }

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

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

    @Override
    public Collection<Object> getCandidates(Object pattern) {
        if (_wantTest) {
            return _placeInstance.getDistinctTestableTokens(pattern);
        } else {
            return _placeInstance.getDistinctTokens(pattern);
        }
    }

    @Override
    public TriggerableCollection getTriggerables() {
        return _placeInstance.triggerables();
    }
}