package de.renew.net.inscription.arc;

import java.util.Collection;
import java.util.Collections;
import java.util.Vector;

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.expression.VariableMapper;
import de.renew.net.NetInstance;
import de.renew.net.SimulatablePlaceInstance;
import de.renew.net.inscription.AbstractOccurrence;
import de.renew.unify.ICalculationChecker;
import de.renew.unify.IStateRecorder;
import de.renew.unify.Impossible;
import de.renew.unify.Variable;

/**
 * A {@code ClearArcOccurrence} is the occurrence of a {@link ClearArc}.
 */
class ClearArcOccurrence extends AbstractOccurrence {
    /** The place instance connected to the arc in the net in which the {@code ClearArcOccurrence} occurs. */
    private final SimulatablePlaceInstance _placeInstance;
    /** The {@code VariableMapper} used for evaluating the arc's inscription. */
    private final VariableMapper _mapper;
    /** The variable for the binding of the clear arc's inscription. */
    private Variable _variable;
    /** The {@code ClearArc} this is an occurrence of. */
    private final ClearArc _arc;

    /**
     * Constructs a new {@code ClearArcOccurrence} based on a clear arc, a {@code variableMapper} and the
     * {@code NetInstance} it occurs in.
     *
     * @param arc the arc that the {@code ClearArcOccurrence} is an occurrence of
     * @param mapper the {@code VariableMapper} used for evaluating the arc's inscription
     * @param netInstance the {@code NetInstance} the {@code ClearArcOccurrence} occurs in
     */
    public ClearArcOccurrence(ClearArc arc, VariableMapper mapper, NetInstance netInstance) {
        super(netInstance.getInstance(arc.getTransition()));
        _arc = arc;
        _mapper = mapper;
        _placeInstance = (SimulatablePlaceInstance) netInstance.getInstance(arc.getPlace());
    }

    @Override
    public Collection<Binder> makeBinders(Searcher searcher) throws Impossible {
        IStateRecorder stateRecorder = searcher.getStateRecorder();
        ICalculationChecker calculationChecker = searcher.getCalculationChecker();
        _variable = new Variable(
            _arc.getExpression().startEvaluation(_mapper, stateRecorder, calculationChecker),
            stateRecorder);

        calculationChecker
            .addCalculated(_arc.getExpression().getType(), _variable, null, stateRecorder);
        return Collections.emptySet();
    }

    @Override
    public Collection<Executable> makeExecutables(VariableMapperCopier variableMapperCopier) {
        Variable copiedVariable = (Variable) variableMapperCopier.getCopier().copy(_variable);
        Collection<Executable> coll = new Vector<>();
        coll.add(new ClearArcExecutable(_placeInstance, copiedVariable, _arc));
        return coll;
    }

    @Override
    public OccurrenceDescription makeOccurrenceDescription(
        VariableMapperCopier variableMapperCopier)
    {
        return null;
    }
}