package de.renew.shadowcompiler;

import de.renew.net.Net;
import de.renew.net.loading.NetLoader;
import de.renew.simulatorontology.shadow.ShadowNet;
import de.renew.simulatorontology.shadow.SyntaxException;


/**
 * Compiles one shadow net. Implementations of this interface are usually
 * instantiated by a {@link ShadowCompilerFactory} implementation.
 * <p>
 * An individual instance of the compiler is needed for each net to
 * compile. However, it is not mandatory that the {@link #createNet} call
 * and the {@link #compile} call occur on the same compiler instance.
 * The information can be transferred between compiler instances by passing
 * the common {@link ShadowLookup} object to {@link #setShadowLookup}.
 * </p>
 *
 * @author Olaf Kummer
 * @author Michael Duvigneau (documentation)
 **/
public interface ShadowCompiler {

    /**
     * Sets the net loader that this compiler uses when a
     * net is found missing amidst compiling.
     *
     * @param loopbackNetLoader the net loader to use when a net is missing
     */
    void setLoopbackNetLoader(NetLoader loopbackNetLoader);

    /**
     * Sets the shadow lookup that will be used for lookups during
     * compilation and that will receive the compilation results.
     *
     * @param shadowLookup the lookup that will contain the compilation results
     */
    void setShadowLookup(ShadowLookup shadowLookup);

    /**
     * Creates one net of the appropriate class, using the given
     * name as the net's name. This method is called before any
     * preprocessors have run and before the compilation has been
     * started.
     *
     * @param name the net's name
     * @return a net with the correct name and class
     */
    Net createNet(String name);

    /**
     * Gets the list of preprocessors that must run before this compiler
     * can start the compilation.
     *
     * @return the preprocessors in an array or the empty array,
     *         if no preprocessors must run
     */
    ShadowPreprocessor[] getRequiredPreprocessors();

    /**
     * Compiles the given net. It is assumed that the method
     * {@link #createNet} with the shadow net's name has been called
     * before. The {@link Net} object created by that call is retrieved
     * from the shadow lookup and filled with the compilation results.
     * <p>
     * The effects of this method are undefined if it is called more than
     * once on the compiler instance. It is also undefined if other
     * compiler instances handle a net with an identical name.
     * </p>
     * See also: {@link #setShadowLookup}
     *
     * @param shadowNet the shadow net to compile
     * @throws SyntaxException if the net cannot be compiled successfully
     **/
    void compile(ShadowNet shadowNet) throws SyntaxException;

    /**
     * Checks the text of a declaration node for syntax errors.
     *
     * @param inscription the inscription of the declaration node to check
     * @param special {@code true} if the declaration node is special,
     *                otherwise {@code false}
     * @param shadowNet the shadow net the declaration node belongs to
     * @return a message containing the result of the syntax check
     * @throws SyntaxException if there is a syntax error in the declaration node
     *                         or declaration nodes aren't supported by the compiler
     */
    String checkDeclarationNode(String inscription, boolean special, ShadowNet shadowNet)
        throws SyntaxException;

    /**
     * Checks the text of an arc inscription for syntax errors.
     *
     * @param inscription the arc inscription to check
     * @param special {@code true} if the arc inscription is special,
     *                otherwise {@code false}
     * @param shadowNet the shadow net the arc inscription belongs to
     * @return a message containing the result of the syntax check
     * @throws SyntaxException if there is a syntax error in the arc inscriptions
     *                         or arc inscriptions aren't supported by the compiler
     */
    String checkArcInscription(String inscription, boolean special, ShadowNet shadowNet)
        throws SyntaxException;

    /**
     * Checks the text of a transition inscription for syntax errors.
     *
     * @param inscription the transition inscription to check
     * @param special {@code true} if the transition inscription is special,
     *                otherwise {@code false}
     * @param shadowNet the shadow net the transition inscription belongs to
     * @return a message containing the result of the syntax check
     * @throws SyntaxException if there is a syntax error in the transition inscription
     *                         or transition inscriptions aren't supported by the compiler
     */
    String checkTransitionInscription(String inscription, boolean special, ShadowNet shadowNet)
        throws SyntaxException;

    /**
     * Checks the text of a place inscription for syntax errors.
     *
     * @param inscription the place inscription to check
     * @param special {@code true} if the place inscription is special,
     *                otherwise {@code false}
     * @param shadowNet the shadow net the place inscription belongs to
     * @return a message containing the result of the syntax check
     * @throws SyntaxException if there is a syntax error in the place inscriptions
     *                         or place inscriptions aren't supported by the compiler
     */
    String checkPlaceInscription(String inscription, boolean special, ShadowNet shadowNet)
        throws SyntaxException;
}