package de.renew.gui.pnml.converter;

import de.renew.formalism.FormalismPlugin;
import de.renew.gui.CPNDrawing;
import de.renew.gui.ModeReplacement;
import de.renew.shadowcompiler.ShadowNetSystemCreator;
import de.renew.simulatorontology.shadow.ShadowNet;


/**
 * Converts between the {@link de.renew.gui.CPNDrawing} representation
 * and the {@link org.w3c.dom.Element} representation (used to generate the PNML file).
 * The result of {@link #getNetConverter()} is most important for this.
 */
public class Converter {
    private static final org.apache.log4j.Logger logger =
        org.apache.log4j.Logger.getLogger(Converter.class);
    private final String _netType;
    private final boolean _toolInsc;
    private ShadowNet net;

    /**
     * Creates a Converter with a net type and sets toolinscription to false.
     *
     * @param type the net type
     */
    public Converter(String type) {
        this(type, false);
    }

    /**
     * Creates a converter with a net type and sets the tool inscription
     *
     * @param type     the net type
     * @param toolInsc whether tool inscription is on or not
     */
    public Converter(String type, boolean toolInsc) {
        _netType = type;
        _toolInsc = toolInsc;
    }

    /**
     * Returns the net type
     *
     * @return the net type
     */
    public String getType() {
        return _netType;
    }

    /**
     * Returns the ShadowNet ID
     *
     * @return the ID
     */
    public String getNetID() {
        return net.getName();
    }

    /**
     * Returns the ShadowNet
     *
     * @return the net
     */
    protected ShadowNet getShadowNet() {
        return net;
    }

    /**
     * Sets the shadow net according to the passed CPNDrawing
     *
     * @param drawing the {@link de.renew.gui.CPNDrawing} representation which gets convertet to a ShadowNet instance
     */
    public void setShadowNet(CPNDrawing drawing) {
        // We can set the formalism to the Java Net Compiler,
        // because the PNML-Reference-Net format can only legally contain
        // reference nets.
        //
        // Note that when the PNML-PT-Net format is used with Renew-specific
        // inscriptions, it can legally contain nets of arbitrary formalisms
        // and when importing it cannot be distinguished between both
        // PNML-PT-Net formats (_toolInsc is only set correctly when exporting).
        // Thus we can not deduce the formalism for the PNML-PT-Net format.
        if (RefNetConverter.isNetParser(_netType)) {
            FormalismPlugin.getCurrent().setCompiler(FormalismPlugin.JAVA_COMPILER);
        }

        net = drawing.buildShadow(
            ShadowNetSystemCreator
                .createWithCompiler(ModeReplacement.getInstance().getDefaultCompilerFactory()));
    }

    /**
     * Returns either an instance of RefNetConverter or an PTNetConverter instance according to the state of the net type being held
     *
     * @return a RefNetConverter if type is PNMLExportFormat.refNetType otherwise a PTNetConverter
     */
    public NetConverter getNetConverter() {
        if (_netType != null) {
            if (RefNetConverter.isNetParser(_netType)) {
                return new RefNetConverter(this, _toolInsc);
            } else if (!PTNetConverter.isNetParser(_netType)) {
                logger
                    .warn(Converter.class.getSimpleName() + ": unknown PNML net type: " + _netType);
            }
        }

        return new PTNetConverter(this, _toolInsc);
    }
}