package de.renew.gui.pnml.creator;

import org.w3c.dom.Element;

import CH.ifa.draw.framework.FigureWithID;
import CH.ifa.draw.framework.ParentFigure;
import de.renew.draw.storables.ontology.FigureEnumeration;
import de.renew.gui.CPNTextFigure;
import de.renew.gui.pnml.converter.Converter;


/**
 * Abstract class for {@link ElementCreator} implementations
 * that create PNML representations for places, transitions and arcs.
 */
public abstract class ObjectCreator extends ElementCreator {
    public ObjectCreator(String tag, Converter converter) {
        super(tag, converter);
    }

    protected FigureWithID getFigure() {
        return (FigureWithID) getObject();
    }

    /**
     * Creates a PNML tag with the name given to {@link #ObjectCreator(String, Converter)}.
     * Sets the {@code id} tag attribute and creates all children
     * using the {@link AttributeCreator} or the {@link AnnotationCreator} class.
     * <p>
     * It also calls {@link #doCreateAttribute(PNMLCreator, Element)}
     * and {@link #doCreateObject(PNMLCreator, Element)} on the PNML tag {@link Element}
     * and appends the {@link Element} created in {@link #doCreateGraphic(GraphicCreator)}.
     * These methods are implemented by the subclasses.
     */
    @Override
    protected Element doCreateElement(PNMLCreator pnmlCreator) {
        Element element = super.doCreateElement(pnmlCreator);
        element.setAttribute("id", xmlID(getFigure()));

        // If it can have children...
        if (getFigure() instanceof ParentFigure parentFigure) {
            // ...retrieve them...
            FigureEnumeration children = parentFigure.children();

            // ...and loop over them:
            while (children.hasMoreElements()) {
                // All children are CPNTextFigures.
                // Get the next child:
                CPNTextFigure annotation = (CPNTextFigure) children.nextElement();

                element.appendChild(
                    getNetConverter().annotationToPNML(annotation, pnmlCreator, false));
            }
        }
        doCreateAttribute(pnmlCreator, element);
        element.appendChild(createGraphic(pnmlCreator));
        doCreateObject(pnmlCreator, element);

        return element;
    }

    private Element createGraphic(PNMLCreator pnmlCreator) {
        GraphicCreator graphicCreator = new GraphicCreator(pnmlCreator);
        doCreateGraphic(graphicCreator);
        return graphicCreator.getElement();
    }

    protected void doCreateAttribute(PNMLCreator pnmlCreator, Element element) {}

    protected void doCreateGraphic(GraphicCreator creator) {}

    protected void doCreateObject(PNMLCreator pnmlCreator, Element element) {}
}