package de.renew.io.exportFormats;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import de.renew.draw.storables.ontology.Drawing;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.storables.ontology.FigureEnumeration;
import de.renew.draw.storables.ontology.exporting.AbstractDrawingExportFormat;
import de.renew.gui.ArcConnection;
import de.renew.gui.CPNDrawing;
import de.renew.gui.ModeReplacement;
import de.renew.gui.PlaceFigure;
import de.renew.gui.ShadowHolder;
import de.renew.gui.TransitionFigure;
import de.renew.io.FileFilterCreator;
import de.renew.simulatorontology.shadow.ShadowArc;
import de.renew.simulatorontology.shadow.ShadowInscription;
import de.renew.simulatorontology.shadow.ShadowPlace;
import de.renew.simulatorontology.shadow.ShadowTransition;

/**
 * Formats Woflan for Export.
 */
public class WoflanExportFormat extends AbstractDrawingExportFormat {

    /**
     * Constructor for WoflanExportFormat
     */
    public WoflanExportFormat() {
        super("Woflan", FileFilterCreator.createWoflanFileFilter());
    }

    @Override
    public boolean canExportNto1() {
        return false;
    }

    @Override
    public File export(Drawing drawing, File path) throws Exception {
        File result = null;
        if (drawing != null && path != null) {
            result = path;
            ModeReplacement.getInstance().getSimulation().buildAllShadows();
            PrintWriter p = new PrintWriter(new FileOutputStream(result));
            int cnt = 0;
            FigureEnumeration placeenumeration = drawing.figures();

            while (placeenumeration.hasMoreElements()) {
                Figure figure = placeenumeration.nextFigure();

                if (figure instanceof PlaceFigure) {
                    ShadowPlace place = (ShadowPlace) ((ShadowHolder) figure).getShadow();
                    String name = place.getName();

                    if (name == null) {
                        name = "P" + (++cnt);
                        place.setName(name);
                    }
                    p.println("place " + name + ";");
                }
            }
            cnt = 0;
            FigureEnumeration transenumeration = drawing.figures();

            while (transenumeration.hasMoreElements()) {
                Figure figure = transenumeration.nextFigure();

                if (figure instanceof TransitionFigure) {
                    ShadowTransition trans = (ShadowTransition) ((ShadowHolder) figure).getShadow();
                    String name = trans.getName();

                    if (name == null) {
                        name = "T" + (++cnt);
                        trans.setName(name);
                    }
                    List<String> inarcs = new ArrayList<>(); // ...of Placenames
                    List<String> outarcs = new ArrayList<>(); // dito


                    // test if transition is :init(...)-transition:

                    for (Object elem : trans.elements()) {
                        if (elem instanceof ShadowInscription shadowInscription
                            && shadowInscription.getInscription().startsWith(":new(")) {
                            inarcs.add("pinit");
                        }
                    }
                    FigureEnumeration arcenumeration = drawing.figures();

                    while (arcenumeration.hasMoreElements()) {
                        figure = arcenumeration.nextFigure();
                        if (figure instanceof ArcConnection ac) {
                            ShadowArc arc = (ShadowArc) ac.getShadow();

                            if (arc.getTransition() == trans) {
                                String placename = arc.getPlace().getName();

                                if (arc.getShadowArcType() == ShadowArc.BOTH
                                    || arc.getShadowArcType() == ShadowArc.TEST) {
                                    inarcs.add(placename);
                                    outarcs.add(placename);
                                } else if (arc.getShadowArcType() == ShadowArc.ORDINARY) {
                                    if (arc.isPlaceToTransition()) {
                                        inarcs.add(placename);
                                    } else {
                                        outarcs.add(placename);
                                    }
                                }
                            }
                        }
                    }
                    p.println(
                        "trans " + name + placeVector(inarcs, " in") + placeVector(outarcs, " out")
                            + ";");
                }
            }
            p.close();
        }
        assert (result != null) : "Failure in WoflanExportFormat: result == null";
        return result;
    }

    @Override
    public File export(Drawing[] drawings, File path) throws Exception {
        File result = null;
        assert (result != null) : "Failure in WoflanExportFormat: result == null";
        return result;
    }

    private String placeVector(List<String> places, String title) {
        StringBuilder output = new StringBuilder();

        if (!places.isEmpty()) {
            output.append(title);
            for (int i = places.size() - 1; i >= 0; --i) {
                output.append(" ").append(places.get(i));
            }
        }
        return output.toString();
    }

    @Override
    public boolean canExportDrawing(Drawing drawing) {
        return drawing instanceof CPNDrawing;
    }
}