package de.renew.gui.fs;

import java.awt.Color;
import java.awt.Point;
import java.io.IOException;
import java.util.Vector;

import CH.ifa.draw.figures.AttributeFigure;
import CH.ifa.draw.figures.ElbowHandle;
import CH.ifa.draw.figures.ElbowTextLocator;
import CH.ifa.draw.standard.ChangeConnectionEndHandle;
import CH.ifa.draw.standard.ChangeConnectionStartHandle;
import CH.ifa.draw.standard.NullHandle;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.storables.ontology.Locator;
import de.renew.draw.storables.ontology.StorableInput;
import de.renew.draw.storables.ontology.StorableOutput;
import de.renew.draw.ui.ontology.FigureHandle;
import de.renew.formalism.fs.ShadowConcept;
import de.renew.formalism.fs.ShadowIsa;
import de.renew.gui.IsaArrowTip;
import de.renew.simulatorontology.shadow.ShadowNetElement;


/**
 * Connection class for an is-a arrow connection.
 */
public class IsaConnection extends ConceptConnection {

    /**
     * Determines type and appearance of the is-a relation.
     * <p>
     * <code>true</code>:  ??? <br>
     * <code>false</code>: ???
     * </p>
     * @serial
     **/
    private boolean _isDisjunctive;

    /**
     * Constructor for the connection.
     * Default sets disjunction to true.
     */
    public IsaConnection() {
        this(true);
    }

    /**
     * Constructor for the connection.
     *
     * @param isDisjunctive sets if disjunction shall be shown
     */
    public IsaConnection(boolean isDisjunctive) {
        super(new IsaArrowTip());
        this._isDisjunctive = isDisjunctive;
        setFillColor(Color.white);
    }

    @Override
    protected ShadowNetElement createShadow(ShadowConcept from, ShadowConcept to) {
        // logger.debug("creating shadow for is-a relation between "+from.getName()+" and "+to.getName());
        return new ShadowIsa(from, to, _isDisjunctive);
    }

    /**
     * Retrieve if disjointness is given.
     *
     * @return disjointness
     */
    public boolean isDisjunctive() {
        return _isDisjunctive;
    }

    @Override
    public void setAttribute(String name, Object value) {
        if (name.equals("IsaType")) {
            _isDisjunctive = ((Boolean) value).booleanValue();
            willChange();
            if (!_isDisjunctive && fPoints.size() > 2) {
                // remove all intermediate points
                Point start = startPoint();
                Point end = endPoint();
                fPoints.removeAllElements();
                fPoints.addElement(start);
                fPoints.addElement(end);
            }
            updateConnection();
            changed();
        } else {
            super.setAttribute(name, value);
        }
    }

    @Override
    public void write(StorableOutput dw) {
        super.write(dw);
        dw.writeBoolean(_isDisjunctive);
    }

    @Override
    public void read(StorableInput dr) throws IOException {
        _isDisjunctive = false; // prevent updatePoints()
        setFillColor(Color.white);
        super.read(dr);
        _isDisjunctive = dr.readBoolean();
    }

    @Override
    public void updateConnection() {
        super.updateConnection();
        if (_isDisjunctive) {
            updatePoints();
        }
    }

    @Override
    public void layoutConnection() {
        if (!_isDisjunctive) {
            super.layoutConnection();
        }
    }

    /**
     * Gets the handles of the figure.
     */
    @Override
    public Vector<FigureHandle> handles() {
        if (_isDisjunctive) {
            Vector<FigureHandle> handles = new Vector<FigureHandle>(fPoints.size() * 2);
            handles.addElement(new ChangeConnectionStartHandle(this));
            for (int i = 1; i < fPoints.size() - 1; i++) {
                handles.addElement(new NullHandle(this, locator(i)));
            }
            handles.addElement(new ChangeConnectionEndHandle(this));
            for (int i = 0; i < fPoints.size() - 1; i++) {
                handles.addElement(new ElbowHandle(this, i));
            }
            return handles;
        } else {
            return super.handles();
        }
    }

    @Override
    public Locator connectedTextLocator(Figure f) {
        if (_isDisjunctive) {
            return new ElbowTextLocator();
        } else {
            return super.connectedTextLocator(f);
        }
    }

    /**
     * Update the points of the connection.
     */
    protected void updatePoints() {
        willChange();
        Point start = startPoint();
        Point end = endPoint();
        fPoints.removeAllElements();
        fPoints.addElement(start);

        if (start.x != end.x && start.y != end.y) {
            fPoints.addElement(new Point(start.x, (start.y + end.y) / 2));
            fPoints.addElement(new Point(end.x, (start.y + end.y) / 2));
        }
        fPoints.addElement(end);
        changed();
    }

    /**
     * Handles the connection of a connection.
     * Override this method to handle this event.
     */
    @Override
    protected void handleConnect(Figure start, Figure end) {
        if (end instanceof ConceptFigure // should be!
            && "interface".equals(((ConceptFigure) end).getStereotype())) {
            setAttribute("LineStyle", AttributeFigure.LINE_STYLE_DASHED);
        }
    }
}