/*
 * @(#)ConnectionFigure.java 5.1
 *
 */

package de.renew.draw.storables.ontology;

import java.awt.Point;

/**
 * Figures to connect Connectors provided by Figures.
 * A ConnectionFigure knows its start and end Connector.
 * It uses the Connectors to locate its connection points.<p>
 * A ConnectionFigure can have multiple segments. It provides
 * operations to split and join segments.
 *
 * <hr>
 * <b>Design Patterns</b><P>
 * <img src="images/red-ball-small.gif" width=6 height=6 alt=" o ">
 * <b><a href=../pattlets/sld034.htm>Strategy</a></b><br>
 * Strategy is used encapsulate the algorithm to locate the connection point.
 * ConnectionFigure is the Strategy context and Connector is the Strategy.<br>
 * <img src="images/red-ball-small.gif" width=6 height=6 alt=" o ">
 * <b><a href=../pattlets/sld026.htm>Observer</a></b><br>
 * Observer is used to track changes of the connected figures. A connection
 * figure registers itself as listeners or observers of the source and
 * target connector.
 * <hr>
 *
 * @see Connector
 */
public interface ConnectionFigure extends Figure, FigureWithDependencies, FigureChangeListener {

    /**
     * Sets the start Connector of the connection.
     * @param start the start figure of the connection
     */
    void connectStart(Connector start);

    /**
     * Sets the end Connector of the connection.
     * @param end the end figure of the connection
     */
    void connectEnd(Connector end);

    /**
     * Updates the connection
     */
    void updateConnection();

    /**
     * Disconnects the start figure from the dependent figure
     */
    void disconnectStart();

    /**
     * Disconnects the end figure from the dependent figure
     */
    void disconnectEnd();

    /**
     * Gets the start Connector.
     * @return start connector
     */
    Connector start();

    /**
     * Gets the end Connector.
     * @return end connector
     */
    Connector end();

    /**
     * Checks if two figures can be connected. Implement this method
     * to constrain the allowed connections between figures.
     * @param start given start figure
     * @param end given end figure
     * @return boolean, {@code true} if able to connect
     */
    boolean canConnect(Figure start, Figure end);

    /**
     * Checks if a figure is a valid start figure candidate for a potential 
     * connection. Implement this method to constrain the allowed start 
     * figures.
     * @param start start to be checked
     * @return boolean, {@code true} by default
     */
    default boolean canConnectStart(Figure start) {
        return true;
    }

    /**
     * Checks if a figure is a valid end figure candidate for a potential 
     * connection. Implement this method to constrain the allowed end figures.
     * @param end end to be checked
     * @return boolean, {@code true} by default
     */
    default boolean canConnectEnd(Figure end) {
        return true;
    }

    /**
     * Checks if the ConnectionFigure connects the same figures.
     * @param other other to be checked
     * @return boolean, {@code true} if same figures are being connected
     */
    boolean connectsSame(ConnectionFigure other);

    /**
     * Sets the start point.
     * @param x point on x-axis
     * @param y point on y-axis
     */
    void startPoint(int x, int y);

    /**
     * Sets the start point.
     * Same as startPoint(p.x, p.y).
     * Override startPoint(int, int), if unsure.
     * @param p start point, to be set
     */
    void startPoint(Point p);

    /**
     * Gets the start point.
     * @return start point
     */
    Point startPoint();

    /**
     * Sets the end point.
     * @param x point on x-axis
     * @param y point on y-axis
     */
    void endPoint(int x, int y);

    /**
     * Sets the end point.
     * Same as endPoint(p.x, p.y).
     * Override endPoint(int, int), if unsure.
     * @param p end point, to be set
     */
    void endPoint(Point p);

    /**
     * Gets the end point.
     * @return end point
     */
    Point endPoint();

    /**
     * Sets the position of the point at the given position.
     * @param p given point, to be set
     * @param index new position
     */
    void setPointAt(Point p, int index);

    /**
     * Gets the Point at the given position.
     * @param index position
     * @return point at index
     */
    Point pointAt(int index);

    /**
     * Gets the number of points or nodes of the connection.
     * @return number of points of connection
     */
    int pointCount();

    /**
     * Splits the hit segment.
     * @param x together with y the position where the figure should be split
     * @param y (see x)
     * @return the index of the splitting point
     */
    int splitSegment(int x, int y);

    /**
     * Joins the hit segments.
     * @param x together with y the position where the figure should be joined.
     * @param y (see x)
     * @return whether the segment was joined
     */
    boolean joinSegments(int x, int y);
}