package routage.fenetre;

import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.graphstream.algorithm.Dijkstra;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;

public class Table extends JPanel {
	HashMap<Node,Node[]> routage;
	
	public Table() {
		this.setBorder(BorderFactory.createTitledBorder("Table de routage"));
	}
	
	public void refreshTable(String node, Graph graph) throws Exception {
		this.removeAll();
		this.routage = routage(node, graph);
		setLayout(new GridLayout(this.routage.size(), this.routage.get((Node)this.routage.keySet().toArray()[0]).length + 1));
		
		List<Node> noeuds = new ArrayList<>(this.routage.keySet());
		Collections.sort(noeuds, new Comparator<Node>(){
			public int compare(Node n1, Node n2) {
				return n1.getId().compareTo(n2.getId());
			}
		});
		
		for(Node noeud:noeuds) {
			this.add(new JLabel("<html><b>" + noeud.getId() + "</b></html>"));
			for(Node temp:this.routage.get(noeud)) {
				Edge edge = graph.getNode(noeud.getId()).getEdgeBetween(temp);
				if (edge != null) {
					this.add(new JLabel(temp.getId() + " (" + edge.getAttribute("weight") + ")"));
				} else {
					this.add(new JLabel(temp.getId() + " (N/A)"));
				}
			}
		}
		
		this.revalidate();
		this.repaint();
	}
	
	public static HashMap<Node, Node[]> routage(String node, Graph graph) throws Exception {
		HashMap<Node, Node[]> retour = new HashMap<>();
		final Node depart = graph.getNode(node);
		ArrayList<Node> voisins = new ArrayList<>();
		
		for(Edge e : depart.getEachEdge())
			voisins.add(e.getOpposite(depart));
		
		for(Node dest:graph.getEachNode()) {
			final Dijkstra d = new Dijkstra(Dijkstra.Element.EDGE, null, "weight");
			d.init(graph);
			d.setSource(dest);
			d.compute();
			
			Collections.sort(voisins, new Comparator<Node>() {
				@Override
				public int compare(Node n1, Node n2) {
                    double p1 = d.getPathLength(n1) + Double.parseDouble(depart.getEdgeBetween(n1).getAttribute("weight").toString());
                    double p2 = d.getPathLength(n2) + Double.parseDouble(depart.getEdgeBetween(n2).getAttribute("weight").toString());
					return Double.compare(p1, p2);
				}
			});
				
			retour.put(dest, Arrays.copyOf(voisins.toArray(), voisins.size(), Node[].class));
		}
		
		return retour;
	}
}
