import org.graphstream.algorithm.APSP;
import org.graphstream.algorithm.Dijkstra;
import org.graphstream.graph.Edge;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.stream.GraphParseException;
import org.graphstream.algorithm.Toolkit;

import java.io.IOException;
import java.sql.SQLOutput;

public class TpPlusCourtChemin {
    public static void main(String[] args) {
        Graph graph = new SingleGraph("leHavre");
        try {
            graph.read("data/lh.dgs");
        } catch (
                IOException e) {
            e.printStackTrace();
        } catch (
                GraphParseException e) {
            e.printStackTrace();
        }


        // Question 1
        graph.addAttribute("ui.stylesheet",
                "node {size: 3px; fill-color: #777; text-mode: hidden; z-index: 0;} " +
                "edge { shape: line; fill-color: #222; arrow-size: 3px, 2px;}");
        graph.addAttribute("ui.quality");
        graph.addAttribute("ui.antialias");

        // Question 2
        int nbNode = graph.getNodeCount();
        System.out.println("noeuds : " + nbNode);
        int nbEdge = graph.getEdgeCount();
        System.out.println("arretes : " + nbEdge);
        double avgD = Toolkit.averageDegree(graph);
        System.out.println("degres : " + avgD);
        int[] distD = Toolkit.degreeDistribution(graph);
        for (int i = 0; i<distD.length; i++) {
            if (distD[i] > 0)
                System.out.printf("%6d%20.8f%n", i, (double)distD[i]/nbNode );
        }
        double avgCC = Toolkit.averageClusteringCoefficient(graph);
        System.out.println("clustering : " + avgCC);

        // Question 3
        Dijkstra dijkstra = new Dijkstra(Dijkstra.Element.EDGE, "result", "length");

        double source = (Math.random() * (graph.getNodeCount()));
        double puit = (Math.random() * (graph.getNodeCount()));

        dijkstra.init(graph);
        dijkstra.setSource(graph.getNode((int)source));
        dijkstra.compute();

        for (Edge edge : dijkstra.getPathEdges(graph.getNode((int)puit))) {
            edge.addAttribute("ui.style", "fill-color: blue;");
            edge.addAttribute("label", edge.getAttribute("length"));
        }



        // Question 7

        long debutD = System.currentTimeMillis();

        // Dijkstra
        double dist = 0;
        double diamD = 0;
        Node diamDS = null;
        Node diamDP = null;
        for (Node s : graph) {
            dijkstra.setSource(s);
            dijkstra.compute();
            for (Node p : graph) {
                double length = dijkstra.getPathLength(p);
                if (length > diamD) {
                    diamD = length;
                    diamDS = s;
                    diamDP = p;
                }
                dist += length;
            }
        }

        System.out.println("Distance moyenne : " + dist/(graph.getNodeCount()*graph.getNodeCount()));

        long finD = System.currentTimeMillis();
        System.out.println("Temps pour dijkstra : " + (finD-debutD));

        // Floyd-Warshall
        APSP apsp = new APSP();
        apsp.init(graph);
        apsp.setDirected(false);
        apsp.setWeightAttributeName("length");
        apsp.compute();

        double diamFW = 0;
        Node diamFWS = null;
        Node diamFWP = null;
        for (Node s : graph) {
            APSP.APSPInfo info = s.getAttribute(APSP.APSPInfo.ATTRIBUTE_NAME);
            for (Node p : graph){
                double length = info.getShortestPathTo(p.getId()).getPathWeight("length");
                if (length > diamFW) {
                    diamFW = length;
                    diamFWS = s;
                    diamFWP = p;
                }
            }
        }

        System.out.println("Temps pour Floyd-Warshall : " + (System.currentTimeMillis()-finD));


        System.out.println(Toolkit.diameter(graph, "length", false));
        System.out.println(diamD);
        System.out.println(diamFW);

        // Affichage du diametre
        dijkstra.setSource(diamDS);
        dijkstra.compute();
        for (Edge edge : dijkstra.getPathEdges(diamDP))
            edge.addAttribute("ui.style", "fill-color: red;");


        graph.display(false);   // No auto-layout.
    }




}
