package de.renew.gui;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Vector;

import CH.ifa.draw.framework.FigureChangeAdapter;
import CH.ifa.draw.standard.FigureEnumerator;
import CH.ifa.draw.standard.MergedFigureEnumerator;
import de.renew.draw.storables.api.StorableApi;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.storables.ontology.FigureChangeEvent;
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.DrawingView;
import de.renew.simulatorontology.shadow.ShadowNet;
import de.renew.simulatorontology.shadow.ShadowNetElement;


/**
 * Instances of this class are virtual transitions.
 * They are graphical copies of their semantic transition.
 * During the simulation, the virtual and semantic transitions are treated as a singular object.
 *  Therefore, they fire as one (including bindings etc.).
 */
public class VirtualTransitionFigure extends TransitionFigure {

    /**
     * The transition figure which is referenced by this virtual
     * transition figure.
     **/
    private TransitionFigure transition = null;

    /**
     * The constructor of virtual transitions used for loading a drawing with virtual transitions.
     * Not to be used by other classes!
     */
    public VirtualTransitionFigure() { // No-Arg-Constructor for loading only!
        super();
    }

    /**
     * Constructor to create a virtual transition.
     * @param transition The semantic transition of this virtual copy.
     */
    public VirtualTransitionFigure(TransitionFigure transition) {
        super();
        setTransition(transition);
    }

    private void setTransition(TransitionFigure transition) {
        this.transition = (TransitionFigure) transition.getSemanticFigure();
        adapt();
        final FigureChangeEvent removeEvent = StorableApi.createFigureChangeEvent(this, null);
        transition.addFigureChangeListener(new FigureChangeAdapter() {
            @Override
            public void figureChanged(FigureChangeEvent e) {
                adapt();
            }

            @Override
            public void figureRemoved(FigureChangeEvent e) {
                if (listener() != null) {
                    listener().figureRequestRemove(removeEvent);
                }
            }
        });
    }

    /**
     * This method returns the transition who is ultimately
     * supposed to be displayed.
     */
    @Override
    public TransitionFigure getSemanticFigure() {
        return (TransitionFigure) transition.getSemanticFigure();
    }

    private void adapt() {
        super.setAttribute("FillColor", transition.getFillColor());
        super.setAttribute("FrameColor", transition.getFrameColor());
    }

    @Override
    public void drawFrame(Graphics g) {
        super.drawFrame(g);
        Rectangle r = displayBox();
        Shape s = new Rectangle2D.Float(r.x + 2, r.y + 2, r.width - 4, r.height - 4);
        ((Graphics2D) g).draw(s);
    }

    @Override
    public ShadowNetElement buildShadow(ShadowNet net) {
        return null;
    }

    @Override
    public ShadowNetElement getShadow() {
        return transition.getShadow();
    }

    @Override
    public void setAttribute(String attr, Object value) {
        if ("FillColor".equals(attr) || "FrameColor".equals(attr)) {
            transition.setAttribute(attr, value);
        } else {
            super.setAttribute(attr, value);
        }
    }

    @Override
    public boolean inspect(DrawingView view, boolean alternate) {
        if (alternate) {
            return super.inspect(view, true);
        } else {
            view.clearSelection();
            view.addToSelection(transition);
            return true;
        }
    }

    @Override
    public FigureEnumeration getFiguresWithDependencies() {
        FigureEnumeration superDep = super.getFiguresWithDependencies();
        Vector<Figure> myDep = new Vector<>(1);
        myDep.addElement(transition);
        return new MergedFigureEnumerator(superDep, new FigureEnumerator(myDep));
    }

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

    /**
     * Reads the Figure from a StorableInput.
     */
    @Override
    public void read(StorableInput dr) throws IOException {
        super.read(dr);
        setTransition((TransitionFigure) dr.readStorable());
    }

    /**
     * Deserialization method, behaves like default readObject
     * method except restoring the connection from this virtual
     * transition to the original transition.
     **/
    private void readObject(java.io.ObjectInputStream in)
        throws IOException, ClassNotFoundException
    {
        in.defaultReadObject();
        setTransition(transition);
    }
}
