package Model;

import java.awt.Color;
import java.util.ArrayList;

import org.eclipse.elk.graph.ElkEdge;
import org.eclipse.elk.graph.ElkNode;

import Algorithms.Animated.BK.ExtremalLayoutCalc.LayoutType;

/**
 * Ein Interface, welches die Methoden eines Knotens aus einem gelayerten Graphen beschreibt (Ein Knoten kann dabei auch einen weiteren Graphen beinhalten)
 * @author kolja
 *
 */
public interface LayeredGraphNode {
    
    // for this node
    
    /**
     * Gibt den originalen Elk Knoten zur�ck
     * @return
     */
    ElkNode getOriginalNode();

    public void setShift( double shift, LayoutType layout );
    public double getShift( LayoutType layout );
    public void setSink( LayeredGraphNode sink, LayoutType layout );
    public LayeredGraphNode getSink( LayoutType layoutType);
    public boolean isXUndefined( LayoutType layout );
    public void setAlignTo( LayeredGraphNode align, LayoutType layout );
    public LayeredGraphNode getAlignedTo( LayoutType layout );
    public void setRoot( LayeredGraphNode root, LayoutType layout );
    public LayeredGraphNode getRoot( LayoutType layout );
    public void setName( String n );
    public String getName();
    public void setColor( Color c, LayoutType layout );
    public Color getColor( LayoutType layout );
    public void update();
    public void setSelected( LayoutType layoutType );
    public boolean isSelected( LayoutType layout );
    public void setDummyNode( boolean dummy );
    public boolean isDummyNode();
    
    /**
     * Setzt den Index des Layers, zu dem der Knoten geh�ren soll
     * @param index Der Index mit 0 beginnend
     */
    void setLayer( int index );
    /**
     * Gibt den Index des Layers zur�ck, dem dieser Knoten angeh�rt
     * @return Der Index des Layers mit 0 beginnend
     */
    int getLayer();
    /**
     * Entfernt den Knoten aus dem Graphen
     */
    void remove();
    /**
     * Ermittelt eine Liste von Kanten, die an diesem Knoten beginnen
     * @return Liste mit Kanten
     */
    ArrayList< LayeredGraphEdge > getOutgoingEdges();
    /**
     * Ermittelt eine Liste von Kanten, die an diesem Knoten enden
     * @return Liste mit Kanten
     */
    ArrayList< LayeredGraphEdge > getIncomingEdges();
    /**
     * Ermittelt eine Liste von Kanten, die an diesem Knoten beginnen
     * @return Liste mit Kanten sortiert nach den positionen der Endknoten in ihrem layer
     */
    ArrayList< LayeredGraphEdge > getSortedOutgoingEdges();
    /**
     * Ermittelt eine Liste von Kanten, die an diesem Knoten enden
     * @return Liste mit Kanten sortiert nach den positionen der Startknoten in ihrem layer
     */
    ArrayList< LayeredGraphEdge > getSortedIncomingEdges();
    /**
     * Gibt den Knoten zur�ck, zu dessen Subgraph dieser Knoten geh�rt
     * @return Der Elternknoten
     */
    LayeredGraphNode parent();
    /**
     * Legt den Knoten fest, zu dessen Subgraph dieser Knoten geh�rt
     * @param parent Der Elternknoten
     */
    void setParent( LayeredGraphNode parent );
    /**
     * Legt die X Koordinate des Knotens fest
     * @param x die X Koordinate in Pixeln
     */
    void setX( double x, boolean def, LayoutType layout );
    /**
     * Legt die Y Koordinate des Knotens Fest
     * @param y die Y Koordinate in Pixeln
     */
    void setY( double y, LayoutType layout );
    /**
     * Gibt die X Koordinate zur�ck
     * @return die X Koordinate in Pixeln zur�ck
     */
    double getX( LayoutType layout );
    /**
     * Gibt die Y Koordinate zur�ck
     * @return die Y Koordinate in Pixeln zur�ck
     */
    double getY( LayoutType layout );
    /**
     * Gibt die Breite des Knotens zur�ck
     * @return die Breite in Pixeln
     */
    double getWidth( LayoutType layout );
    /**
     * Gibt die H�he des Knotens zur�ck
     * @return die H�he in Pixeln
     */
    double getHeight( LayoutType layout );
    
    void setWidth( double w, LayoutType layout );
    void setHeight( double h, LayoutType layout );
    
    // for subgraph
    
    /**
     * Ermittelt den Index des Layers, dem ein Knoten angeh�rt
     * @param n der Knoten, zu dem der Layerindex gesucht wird
     * @return der Index des Layers mit 0 beginnend
     */
    int getNodeLayer( LayeredGraphNode n );
    /**
     * Sortiert einen Layer nach bestimmten Gewichten
     * Die Knoten mit dem geringsten Gewicht kommen vor den Knoten mit gr��erem Gewicht
     * @param indizes Eine Liste mit einem Gewicht f�r jeden Knoten
     * @param layerIndex Der Index des Layers, der sortiert werden soll
     */
    void setOrderedLayer( ArrayList< Double > indizes, int layerIndex );
    /**
     * Legt fest zu welchem Layer ein bestimmter Knoten geh�rt
     * @param n Der Knoten
     * @param index Der Index des Layers
     */
    void setNodeLayer( LayeredGraphNode n, int index );
    /**
     * @return Eine Liste mit allen Kanten des Subgraphen
     */
    ArrayList< LayeredGraphEdge > getContainedEdges();
    /**
     * @return Eine Liste mit allen Knoten des Subgraphen
     */
    ArrayList< LayeredGraphNode > getContainedNodes();
    /**
     * @return Eine Liste mit allen Knoten des Subgraphen sortiert nach Layern und Positionen
     */
    ArrayList< LayeredGraphNode > getSortedContainedNodes();
    /**
     * @return Eine Liste mit allen Layern des Subgraphen
     */
    ArrayList< ArrayList< LayeredGraphNode > > getContainedLayers();
    /**
     * Entfernt eine Kante aus dem Subgraph
     * @param e die Kante, die entfernt werden soll
     */
    void removeEdge( LayeredGraphEdge e );
    /**
     * Entfernt einen Knoten aus dem Subgraph
     * @param n der Knoten, die entfernt werden soll
     */
    void removeNode( LayeredGraphNode n );
    /**
     * Ermittelt eine Liste von ausgehenden Kanten eines Knotens
     * @param n Der Knoten
     * @return Die Liste mit Kanten
     */
    ArrayList< LayeredGraphEdge > getOutgoingEdges( LayeredGraphNode n );
    /**
     * Ermittelt eine Liste von ausgehenden Kanten eines Knotens
     * @param n Der Knoten
     * @return Die Liste mit Kanten sortiert nach den positionen der Endknoten in ihren Layern
     */
    ArrayList< LayeredGraphEdge > getSortedOutgoingEdges( LayeredGraphNode n );
    /**
     * Ermittelt eine Liste von eingehenden Kanten eines Knotens
     * @param n Der Knoten
     * @return Die Liste mit Kanten
     */
    ArrayList< LayeredGraphEdge > getIncomingEdges( LayeredGraphNode n );
    /**
     * Ermittelt eine Liste von eingehenden Kanten eines Knotens
     * @param n Der Knoten
     * @return Die Liste mit Kanten sortiert nach den positionen der Startknoten in ihren Layern
     */
    ArrayList< LayeredGraphEdge > getSortedIncomingEdges( LayeredGraphNode n );
    
    /**
     * F�gt einen neuen Knoten zum Subgraph hinzu
     * @param original Der originale Elk Knoten
     * @return Der neu erzeugte Knoten
     */
    LayeredGraphNode createNode( ElkNode original );
    /**
     * F�gt eine neue Kante zum Subgraph hinzu
     * @param original Die Originale Elk Kante
     * @param sources Eine Liste mit Startknoten
     * @param targets Eine Liste mit Endknoten
     * @return Die neue Kante
     */
    LayeredGraphEdge createEdge( ElkEdge original, ArrayList< LayeredGraphNode > sources, ArrayList< LayeredGraphNode > targets );
    /**
     * F�gt eine neue Kante zum Subgraph hinzu
     * @param original Die Originale Elk Kante
     * @param sources Der Startknoten
     * @param targets Der Endknoten
     * @return Die neue Kante
     */
    LayeredGraphEdge createSimpleEdge( ElkEdge original, LayeredGraphNode source, LayeredGraphNode target );
    /**
     * Findet zu einer Originalen Kante eine Layered Kante
     * @param original die originale Kante
     * @return die layered Kante
     */
    LayeredGraphEdge findEdgeFromOriginal( Object original );
    /**
     * Findet zu einem Originalen Knoten einen Layered Knoten
     * @param original der originale Knoten
     * @return der layered Knoten
     */
    LayeredGraphNode findNodeFromOriginal( Object original );
    
    LayeredGraphNode findNodeByName( String name );
    /**
     * F�gt einen Knoten zum Subgraphen hinzu
     * @param n Der neue Knoten
     */
    void addNode( LayeredGraphNode n );
    /**
     * F�gt eine Kante zum Subgraphen hinzu
     * @param e Die neue Kante
     */
    void addEdge( LayeredGraphEdge e );
}
