package unlh.ri;

import org.graphstream.algorithm.Toolkit;
import org.graphstream.graph.BreadthFirstIterator;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.stream.file.FileSourceEdge;
import java.io.*;
import java.util.*;

public class MesuresRI {

    private static final String FILE_PATH = "data/com-dblp.ungraph.txt";
    private static final String OUTPUT_DATA = "data/dd_dblp.dat";

    public static void main(String... args) throws IOException {
        Graph graph = new DefaultGraph("g");
        FileSourceEdge fs = new FileSourceEdge();
        BufferedWriter writer = new BufferedWriter(new FileWriter(OUTPUT_DATA));

        try {
            fs.addSink(graph);
            fs.readAll(FILE_PATH);

            System.out.println("N :" + graph.getNodeCount());
            System.out.println("L :" + graph.getEdgeCount());
            System.out.println("<k> :" + Toolkit.averageDegree(graph));
            System.out.println("<C>:" + Toolkit.averageClusteringCoefficient(graph));
            System.out.println("Connexe : " + Toolkit.isConnected(graph));

            int[] dd = Toolkit.degreeDistribution(graph);
            for (int k = 0; k < dd.length; k++) {
                if (dd[k] != 0) {
                    writer.write(String.format(Locale.US, "%6d%20.8f%n", k, (double) dd[k] / graph.getNodeCount()));
                }
            }

            int len = 1000, cpt = 0;
            double distance = 0, nb = 0, avgDistance;
            List<Node> randomNodeSet = Toolkit.randomNodeSet(graph, len);
            HashMap<Integer, Double> distancesMap = new HashMap<Integer, Double>();

            for (Node currNode : randomNodeSet) {
                BreadthFirstIterator<Node> bfi = new BreadthFirstIterator<>(currNode);
                while (bfi.hasNext()) {
                    Node opNode = bfi.next();
                    Integer key = bfi.getDepthOf(opNode);
                    distancesMap.put(key, distancesMap.containsKey(key) ? 1 + distancesMap.get(key) : 1);
                    distance += bfi.getDepthOf(opNode);
                    nb++;
                }
                cpt++;
            }
            avgDistance = distance / nb;
            System.out.println("Average distance :" + avgDistance);

            // Normalisation et ecriture dans data/distances.dat //
            Double total = distancesMap
                    .values()
                    .stream()
                    .reduce(0.0, Double::sum)
                    .doubleValue();

            writer.flush();
            writer.close();

            writer = new BufferedWriter(new FileWriter("data/distances.dat"));
            for (Integer name : distancesMap.keySet()) {
                String key = name.toString();
                Double value = Double.valueOf(distancesMap.get(name));
                writer.write(String.format(Locale.US, "%6s%20.8f%n", key, value/total));
            }
            // graph.display();

        } catch (IOException e) {
            e.printStackTrace();
            fs.end();
        } finally {
            writer.close();
            fs.removeSink(graph);
        }
    }
}


