package de.renew.formalism.java;

import de.renew.expression.ConstantExpression;
import de.renew.expression.Expression;
import de.renew.net.Place;
import de.renew.net.Transition;
import de.renew.net.inscription.arc.Arc;
import de.renew.simulatorontology.shadow.SyntaxException;

/**
 * Factory class for creating arcs with specific characteristics like fixed type and optional time expression.
 */
public class SimpleArcFactory implements ArcFactory {

    /**
     * The type of the arc.
     */
    protected Arc.Type _arcType;

    /**
     * Whether the arc allows timed inscriptions.
     */
    protected boolean _allowsTime;

    /**
     * Creates an instance with arc type and time setting.
     * @param arcType the type of the arc
     * @param allowsTime whether the arc allows timed inscriptions
     */
    public SimpleArcFactory(Arc.Type arcType, boolean allowsTime) {
        this._arcType = arcType;
        this._allowsTime = allowsTime;
    }

    @Override
    public void emptyArcCheck() {}

    @Override
    public boolean allowsTime() {
        return _allowsTime;
    }

    /**
     * Makes and returns an arc with given details.
     * @param place the place that the arc connects to
     * @param transition the transition that the arc connects to
     * @param arcType the type of the arc
     * @param expr the expression used for the arc
     * @param timeExpr the time expression for the arc
     * @return the new Arc object
     */
    protected Arc getArc(
        Place place, Transition transition, Arc.Type arcType, Expression expr, Expression timeExpr)
    {
        return new Arc(place, transition, arcType, expr, timeExpr);
    }

    @Override
    public void compileArc(
        Place place, Transition transition, boolean trace, Class<?> placeType, ArcInscription insc)
        throws SyntaxException
    {
        Expression expr;
        if (_arcType == Arc.Type.OUT) {
            expr = JavaNetHelper.makeCastedOutputExpression(placeType, insc.getExpression());
        } else {
            expr = JavaNetHelper.makeCastedInputExpression(placeType, insc.getExpression());
        }

        Expression timeExpr = null;
        if (_allowsTime) {
            if (insc.isTimed()) {
                timeExpr = insc.getTime().getExpression();
            } else {
                timeExpr = ConstantExpression.DOUBLE_ZERO_EXPRESSION;
            }
        }

        Arc arc = getArc(place, transition, _arcType, expr, timeExpr);
        arc.setTrace(trace);
        transition.add(arc);
    }
}