package Model;

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

import javax.swing.SwingUtilities;

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

import Algorithms.Animated.BK.ExtremalLayoutCalc.LayoutType;
import View.MainView;

/**
 * Die Implementation eines Knotens in einem Layered Graph.
 * Implementiert {@link LayeredGraphNode.}
 * 
 * @author kolja
 *
 */
public class LayeredNode implements LayeredGraphNode {

    // for this node
    private ElkNode original;
    private LayeredGraphNode parent;
    
    private class LayoutInfo
    {
        public double x;
        public double y;
        public double w;
        public double h;
        public Color color;
        public boolean selected;
        public boolean xUndef;
        
        // Block Calculation
        public LayeredGraphNode align;
        public LayeredGraphNode root;
        // Compaction
        public LayeredGraphNode sink;
        public double shift;
    }
    LayoutInfo[] layouts;
    
    String name;
    
    // for subgraph in this node
    private ArrayList< LayeredGraphEdge > edges;
    private ArrayList< LayeredGraphNode > nodes;
    private ArrayList< ArrayList< LayeredGraphNode > > layers;
    
    public LayeredNode( ElkNode original, LayeredGraphNode parent )
    {
        this.original = original;
        this.parent = parent;
        
        edges = new ArrayList<>();
        nodes = new ArrayList<>();
        layers = new ArrayList<>();
        layouts = new LayoutInfo[ 4 ];
        for( int i = 0; i < 4; i++ )
            layouts[ i ] = new LayoutInfo();
        for( LayoutInfo l : layouts )
        {
            if( original != null )
            {
            	l.x = original.getX();
            	l.y = original.getX();
            	l.w = original.getWidth();
            	l.h = original.getHeight();
            }
            l.align = this;
            l.root = this;
            l.sink = this;
            l.shift = Double.POSITIVE_INFINITY;
            l.xUndef = true;
        }
    }

    @Override
    public void setShift( double shift, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].shift = shift;
            this.layouts[ 1 ].shift = shift;
            this.layouts[ 2 ].shift = shift;
            this.layouts[ 3 ].shift = shift;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].shift = shift;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].shift = shift;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].shift = shift;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].shift = shift;
    }
    
    @Override
    public double getShift( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].shift;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].shift;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].shift;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].shift;
        return 0;
    }

    @Override
    public void setSink( LayeredGraphNode sink, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].sink = sink;
            this.layouts[ 1 ].sink = sink;
            this.layouts[ 2 ].sink = sink;
            this.layouts[ 3 ].sink = sink;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].sink = sink;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].sink = sink;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].sink = sink;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].sink = sink;
    }
    
    @Override
    public LayeredGraphNode getSink( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].sink;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].sink;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].sink;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].sink;
        return null;
    }
    
    @Override
    public boolean isXUndefined( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].xUndef;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].xUndef;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].xUndef;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].xUndef;
        return true;
    }

    @Override
    public void setAlignTo( LayeredGraphNode align, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].align = align;
            this.layouts[ 1 ].align = align;
            this.layouts[ 2 ].align = align;
            this.layouts[ 3 ].align = align;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].align = align;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].align = align;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].align = align;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].align = align;
    }

    @Override
    public LayeredGraphNode getAlignedTo( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].align;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].align;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].align;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].align;
        return null;
    }

    @Override
    public void setRoot( LayeredGraphNode root, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].root = root;
            this.layouts[ 1 ].root = root;
            this.layouts[ 2 ].root = root;
            this.layouts[ 3 ].root = root;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].root = root;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].root = root;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].root = root;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].root = root;
    }

    @Override
    public LayeredGraphNode getRoot( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].root;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].root;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].root;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].root;
        return null;
    }

    @Override
    public void update()
    {
    	SwingUtilities.invokeLater(new Runnable() {
		    public void run() {
		        MainView.frame.repaint();
		    }
		});
    }

    @Override
    public void setSelected( LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].selected = true;
            this.layouts[ 1 ].selected = true;
            this.layouts[ 2 ].selected = true;
            this.layouts[ 3 ].selected = true;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].selected = true;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].selected = true;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].selected = true;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].selected = true;
    	update();
    }

    @Override
    public boolean isSelected( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
        {
            boolean tmp = layouts[ 0 ].selected;
            layouts[ 0 ].selected = false;
            return tmp;
        }
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
        {
            boolean tmp = layouts[ 1 ].selected;
            layouts[ 1 ].selected = false;
            return tmp;
        }
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
        {
            boolean tmp = layouts[ 2 ].selected;
            layouts[ 2 ].selected = false;
            return tmp;
        }
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
        {
            boolean tmp = layouts[ 3 ].selected;
            layouts[ 3 ].selected = false;
            return tmp;
        }
        return false;
    }
    
    @Override
    public void setColor( Color c, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].color = c;
            this.layouts[ 1 ].color = c;
            this.layouts[ 2 ].color = c;
            this.layouts[ 3 ].color = c;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].color = c;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].color = c;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].color = c;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].color = c;
    }
    
    @Override
    public Color getColor( LayoutType layout )
    {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].color;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].color;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].color;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].color;
        return null;
    }
    
    @Override
    public void setName( String n ) {
    	name = n;
    }
    
    @Override
    public String getName()
    {
    	return name;
    }
    
    @Override
    public ElkNode getOriginalNode() {
        return original;
    }

    @Override
    public void remove() {
        parent.removeNode( this );
    }

    @Override
    public LayeredGraphNode parent() {
        return parent;
    }

    @Override
    public void setLayer(int index) {
        parent.setNodeLayer( this, index );
    }

    @Override
    public int getLayer() {
        return parent.getNodeLayer( this );
    }

    @Override
    public void setX(double x, boolean def, LayoutType layout ) {
        if( layout == null )
        {
            layouts[ 0 ].x = x;
            layouts[ 1 ].x = x;
            layouts[ 2 ].x = x;
            layouts[ 3 ].x = x;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
        {
            layouts[ 0 ].xUndef = !def;
            layouts[ 0 ].x = x;
        }
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
        {
            layouts[ 1 ].xUndef = !def;
            layouts[ 1 ].x = x;
        }
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
        {
            layouts[ 2 ].xUndef = !def;
            layouts[ 2 ].x = x;
        }
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
        {
            layouts[ 3 ].xUndef = !def;
            layouts[ 3 ].x = x;
        }
    }

    @Override
    public void setY(double y, LayoutType layout ) {
        if( layout == null )
        {
            layouts[ 0 ].y = y;
            layouts[ 1 ].y = y;
            layouts[ 2 ].y = y;
            layouts[ 3 ].y = y;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            layouts[ 0 ].y = y;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            layouts[ 1 ].y = y;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            layouts[ 2 ].y = y;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            layouts[ 3 ].y = y;
    }

    @Override
    public double getX( LayoutType layout ) {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].x;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].x;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].x;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].x;
        return 0;
    }

    @Override
    public double getY( LayoutType layout ) {
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return this.layouts[ 0 ].y;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return this.layouts[ 1 ].y;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return this.layouts[ 2 ].y;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return this.layouts[ 3 ].y;
        return 0;
    }

    @Override
    public double getWidth( LayoutType layout ) {
        if( nodes.size() > 0 )
        {
            double max = 0;
            double min = Double.POSITIVE_INFINITY;
            for( LayeredGraphNode n : nodes )
            {
                if( max < n.getX(layout) + n.getWidth(layout) + 50 )
                    max = n.getX(layout) + n.getWidth(layout) + 50;
                min = Math.min( n.getX(layout), min);
            }
            if( layout == LayoutType.TOP_BOTTOM_LEFT )
                return Math.max( max - min, layouts[ 0 ].w );
            if( layout == LayoutType.TOP_BOTTOM_RIGHT )
                return Math.max( max - min, layouts[ 1 ].w );
            if( layout == LayoutType.BOTTOM_TOP_LEFT )
                return Math.max( max - min, layouts[ 2 ].w );
            if( layout == LayoutType.BOTTOM_TOP_RIGHT )
                return Math.max( max - min, layouts[ 3 ].w );
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return layouts[ 0 ].w;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return layouts[ 1 ].w;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return layouts[ 2 ].w;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return layouts[ 3 ].w;
        return 0;
    }

    @Override
    public double getHeight( LayoutType layout ) {
        if( nodes.size() > 0 )
        {
        	double max = 0;
        	for( LayeredGraphNode n : nodes )
        	{
        		if( max < n.getY(layout) + n.getHeight(layout) + 50 )
        			max = n.getY(layout) + n.getHeight(layout) + 50;
        	}
            if( layout == LayoutType.TOP_BOTTOM_LEFT )
                return Math.max( max, layouts[ 0 ].h );
            if( layout == LayoutType.TOP_BOTTOM_RIGHT )
                return Math.max( max, layouts[ 1 ].h );
            if( layout == LayoutType.BOTTOM_TOP_LEFT )
                return Math.max( max, layouts[ 2 ].h );
            if( layout == LayoutType.BOTTOM_TOP_RIGHT )
                return Math.max( max, layouts[ 3 ].h );
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            return layouts[ 0 ].h;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            return layouts[ 1 ].h;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            return layouts[ 2 ].h;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            return layouts[ 3 ].h;
        return 0;
    }
    
    @Override
    public void setWidth( double w, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].w = w;
            this.layouts[ 1 ].w = w;
            this.layouts[ 2 ].w = w;
            this.layouts[ 3 ].w = w;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].w = w;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].w = w;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].w = w;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].w = w;
    }
    
    @Override
    public void setHeight( double h, LayoutType layout )
    {
        if( layout == null )
        {
            this.layouts[ 0 ].h = h;
            this.layouts[ 1 ].h = h;
            this.layouts[ 2 ].h = h;
            this.layouts[ 3 ].h = h;
        }
        if( layout == LayoutType.TOP_BOTTOM_LEFT )
            this.layouts[ 0 ].h = h;
        if( layout == LayoutType.TOP_BOTTOM_RIGHT )
            this.layouts[ 1 ].h = h;
        if( layout == LayoutType.BOTTOM_TOP_LEFT )
            this.layouts[ 2 ].h = h;
        if( layout == LayoutType.BOTTOM_TOP_RIGHT )
            this.layouts[ 3 ].h = h;
    }

    @Override
    public void removeEdge(LayeredGraphEdge e) {
        edges.remove( e );
    }

    @Override
    public void removeNode(LayeredGraphNode n) {
        for( LayeredGraphEdge e : n.getIncomingEdges() )
            e.remove();
        for( LayeredGraphEdge e : n.getOutgoingEdges() )
            e.remove();
        nodes.remove( n );
        for( ArrayList<LayeredGraphNode> l : layers )
        {
            l.remove( n );
        }
    }

    @Override
    public void setNodeLayer(LayeredGraphNode n, int index) {
        while( index >= layers.size() )
            layers.add( new ArrayList<>() );
        int old = n.getLayer();
        if( old >= 0 )
            layers.get( old ).remove( n );
        layers.get( index ).add( n );
    }

    @Override
    public void setOrderedLayer(ArrayList<Double> indizes, int layerIndex) {
        ArrayList<LayeredGraphNode> l2 = layers.get( layerIndex );
        ArrayList<LayeredGraphNode> result = new ArrayList<LayeredGraphNode>();
        while( indizes.size() > 0 )
        {
            int mIndex = 0;
            double min = indizes.get( 0 );
            for( int i = 1; i < indizes.size(); i++ )
            {
                if( min > indizes.get( i ) )
                {
                    mIndex = i;
                    min = indizes.get( i );
                }
            }
            result.add( l2.get( mIndex ) );
            l2.remove( mIndex );
            indizes.remove( mIndex );
        }
        layers.set( layerIndex, result );
    }
    
    @Override
    public ArrayList<LayeredGraphEdge> getOutgoingEdges() {
        return parent.getOutgoingEdges( this );
    }
    
    @Override
    public ArrayList<LayeredGraphEdge> getSortedOutgoingEdges() {
        return parent.getSortedOutgoingEdges( this );
    }

    @Override
    public ArrayList<LayeredGraphEdge> getIncomingEdges() {
        return parent.getIncomingEdges( this );
    }

    @Override
    public ArrayList<LayeredGraphEdge> getSortedIncomingEdges() {
        return parent.getSortedIncomingEdges( this );
    }

    @Override
    public ArrayList<LayeredGraphEdge> getContainedEdges() {
        return edges;
    }

    @Override
    public ArrayList<LayeredGraphNode> getContainedNodes() {
        return nodes;
    }
    
    @Override
    public ArrayList< LayeredGraphNode > getSortedContainedNodes()
    {
        ArrayList< LayeredGraphNode > result = new ArrayList<>();
        for( ArrayList<LayeredGraphNode> l : layers )
        {
            result.addAll( l );
        }
        return result;
    }

    @Override
    public ArrayList<ArrayList<LayeredGraphNode>> getContainedLayers() {
        return layers;
    }

    @Override
    public int getNodeLayer(LayeredGraphNode n) {
        for( int i = 0; i < layers.size(); i++ )
        {
            if( layers.get( i ).contains( n ) )
                return i;
        }
        return -1;
    }

    @Override
    public ArrayList<LayeredGraphEdge> getOutgoingEdges(LayeredGraphNode n) {
        ArrayList<LayeredGraphEdge> result = new ArrayList<>();
        for( LayeredGraphEdge e : edges )
        {
            if( e.getSources().contains( n ) )
                result.add( e );
        }
        return result;
    }

    @Override
    public ArrayList<LayeredGraphEdge> getIncomingEdges(LayeredGraphNode n) {
        ArrayList<LayeredGraphEdge> result = new ArrayList<>();
        for( LayeredGraphEdge e : edges )
        {
            if( e.getTargets().contains( n ) )
                result.add( e );
        }
        return result;
    }

    @Override
    public ArrayList<LayeredGraphEdge> getSortedOutgoingEdges(LayeredGraphNode n) {
        ArrayList<LayeredGraphEdge> result = new ArrayList<>();
    	if( n.getLayer() + 1 >= layers.size() )
    		return result;
        ArrayList< LayeredGraphEdge > unsorted = getOutgoingEdges( n );
        for( LayeredGraphNode node : layers.get( n.getLayer() + 1 ) )
        {
        	for( LayeredGraphEdge e : unsorted )
            {
                if( e.getTargets().contains( node ) )
                	result.add( e );
            }
        }
        return result;
    }

    @Override
    public ArrayList<LayeredGraphEdge> getSortedIncomingEdges(LayeredGraphNode n) {
        ArrayList<LayeredGraphEdge> result = new ArrayList<>();
    	if( n.getLayer() - 1 < 0 )
    		return result;
        ArrayList< LayeredGraphEdge > unsorted = getIncomingEdges( n );
        for( LayeredGraphNode node : layers.get( n.getLayer() - 1 ) )
        {
        	for( LayeredGraphEdge e : unsorted )
            {
                if( e.getSources().contains( node ) )
                	result.add( e );
            }
        }
        return result;
    }

    @Override
    public LayeredGraphNode createNode(ElkNode original) {
        LayeredGraphNode n = new LayeredNode( original, this );
        nodes.add( n );
        return n;
    }

    @Override
    public LayeredGraphEdge createEdge(ElkEdge original, ArrayList<LayeredGraphNode> sources, ArrayList<LayeredGraphNode> targets) {
        LayeredGraphEdge e = new LayeredEdge( original, sources, targets, this );
        edges.add( e );
        return e;
    }

    @Override
    public LayeredGraphEdge createSimpleEdge(ElkEdge original, LayeredGraphNode source, LayeredGraphNode target) {
        ArrayList<LayeredGraphNode> sources = new ArrayList<>();
        ArrayList<LayeredGraphNode> targets = new ArrayList<>();
        sources.add( source );
        targets.add( target );
        LayeredGraphEdge e = new LayeredEdge( original, sources, targets, this );
        edges.add( e );
        return e;
    }
    
    @Override
    public LayeredGraphEdge findEdgeFromOriginal(Object original) {
        for( LayeredGraphEdge e : edges )
        {
            if( e.getOriginalEdge() == original )
                return e;
        }
        return null;
    }

    @Override
    public LayeredGraphNode findNodeFromOriginal(Object original) {
        for( LayeredGraphNode n : nodes )
        {
            if( n.getOriginalNode() == original )
                return n;
        }
        return null;
    }
    
    @Override
    public LayeredGraphNode findNodeByName( String name )
    {
    	for( LayeredGraphNode n : nodes )
        {
            if( n.getName() != null && name != null && n.getName().equals( name ) )
                return n;
        }
        return null;	
    }

    @Override
    public void addNode(LayeredGraphNode n) {
        nodes.add( n );
        n.setParent( this );
    }

    @Override
    public void addEdge(LayeredGraphEdge e) {
        edges.add( e );
        e.setGraph( this );
    }

    @Override
    public void setParent(LayeredGraphNode parent) {
        this.parent = parent;
    }
}
