/*
 * @(#)PlaceFigure.java 5.1
 *
 */
package de.renew.gui;

import java.awt.Dimension;
import java.awt.Graphics;
import java.io.IOException;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Vector;

import CH.ifa.draw.figures.EllipseFigure;
import CH.ifa.draw.standard.FigureEnumerator;
import CH.ifa.draw.standard.MergedFigureEnumerator;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.storables.ontology.FigureEnumeration;
import de.renew.draw.storables.ontology.StorableInput;
import de.renew.draw.storables.ontology.StorableOutput;
import de.renew.draw.ui.ontology.FigureHandle;
import de.renew.remote.ObjectAccessor;
import de.renew.simulatorontology.shadow.ShadowNet;
import de.renew.simulatorontology.shadow.ShadowNetElement;
import de.renew.simulatorontology.shadow.ShadowPlace;


public class PlaceFigure extends EllipseFigure
    implements PlaceNodeFigure, FigureWithHighlight, InscribableFigure, SimulableFigure
{
    /*
     * Serialization support.
     */
    private static final long serialVersionUID = -7878886241236946512L;
    public static final int HIGHLIGHT = 0;
    public static final int CARDINALITY = 1;
    public static final int TOKENS = 2;
    public static final int EXPANDED_TOKENS = 3;
    @SuppressWarnings("unused")
    private final int placeFigureSerializedDataVersion = 1;

    /**
     * This figure will be highlighted in a instance
     * drawing in the same manner as the place figure
     * will be highlighted. May be <code>null</code>.
     * @serial
     **/
    private Figure hilightFig = null;

    /**
     * The shadow of this place figure.
     * Initially <code>null</code>, will be created
     * when needed.
     * <p>
     * This field is transient because its information
     * can be regenerated via <code>buildShadow(...)</code>.
     * </p>
     **/
    protected transient ShadowPlace shadow = null;

    public PlaceFigure() {
        super();
    }

    @Override
    public Vector<FigureHandle> handles() {
        Vector<FigureHandle> handles = super.handles();
        handles.addElement(new ArcConnectionHandle(this));
        return handles;
    }

    @Override
    public void draw(Graphics g) {
        super.draw(g);
        if (isVisible() && getAttribute(Breakpoint.ATTRIBUTENAME) != null) {
            BreakpointDecoration.draw(g, displayBox());
        }
    }

    public boolean getTraceMode() {
        Object value = getAttribute("TraceMode");
        if (value instanceof Boolean bool) {
            return bool;
        }
        return true;
    }

    public int getMarkingAppearance() {
        Object value = getAttribute("MarkingAppearance");
        if (value instanceof Integer integer) {
            return integer;
        }
        return CARDINALITY;
    }

    @Override
    public void release() {
        setHighlightFigure(null);
        super.release();
        if (shadow != null) {
            shadow.discard();
        }
    }

    @Override
    public ShadowNetElement buildShadow(ShadowNet net) {
        if (shadow != null) {
            shadow.discard();
        }
        shadow = new ShadowPlace(net);
        shadow.setContext(this);
        shadow.setID(this.getID());
        shadow.setTrace(getTraceMode());
        return shadow;
    }

    @Override
    public ShadowNetElement getShadow() {
        return shadow;
    }

    public static Dimension defaultDimension() {
        return new Dimension(20, 20);
    }

    @Override
    public void setHighlightFigure(Figure fig) {
        hilightFig = fig;
    }

    @Override
    public Figure getHighlightFigure() {
        return hilightFig;
    }

    /**
     * Returns all figures with dependencies of the superclass
     * plus an optional hilight figure.
     */
    @Override
    public FigureEnumeration getFiguresWithDependencies() {
        FigureEnumeration superDep = super.getFiguresWithDependencies();
        Vector<Figure> myDep = new Vector<>(1);
        myDep.addElement(getHighlightFigure());
        return new MergedFigureEnumerator(superDep, new FigureEnumerator(myDep));
    }


    /**
     * Creates an instance figure for this figure.
     * @param drawing The instance drawing to create the figure for.
     * @param netElements The net elements.
     * @return The new instance figure.
     */
    @Override
    public InstanceFigure createInstanceFigure(
        InstanceDrawing drawing, Hashtable<Serializable, ObjectAccessor> netElements)
    {
        return new PlaceInstanceFigure(drawing, this, netElements);
    }

    /**
     * Stores the Figure to a StorableOutput.
     */
    @Override
    public void write(StorableOutput dw) {
        super.write(dw);
        dw.writeStorable(hilightFig);
    }

    /**
     * Reads the Figure from a StorableInput.
     */
    @Override
    public void read(StorableInput dr) throws IOException {
        super.read(dr);
        if (dr.getVersion() >= 3) {
            setHighlightFigure((Figure) dr.readStorable());
        }
    }
}