import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;

import org.graphstream.graph.BreadthFirstIterator;
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.file.FileSourceEdge;
import org.graphstream.algorithm.Toolkit;

public class App {
    public static void main(String[] args) throws IOException{
        String filePath = "com-dblp.ungraph.txt";
		Graph g = new SingleGraph("g");
        FileSourceEdge fse = new FileSourceEdge();
        
		fse.addSink(g);
        System.out.println("Flag 1");
		try {
			fse.readAll(filePath);
		} catch( IOException e) {
			e.printStackTrace();
		}

        

        int N = g.getNodeCount();
        int L = g.getEdgeCount();
        double p = 1.0/N;
        double K = Toolkit.averageDegree(g);
        double C = Toolkit.averageClusteringCoefficient(g);

        System.out.println("Noeuds : " + N); // N
        System.out.println("Arêtes : " + L); // L
        System.out.println("Degré moyen : " + K); // <k> = 2L/N
        System.out.println("Coefficient de clustering moyen : " + C); // <C>

        System.out.println("p = " + p);
        System.out.println("p > ln N / N : " + (p > Math.log(N)/N));
        System.out.println("<k> > ln N : " + ( K > Math.log(N)));
        System.out.println("Pour qu'il soit connexe, il faut <k> > " + Math.log(N));
        
        int[] distributionDegres = Toolkit.degreeDistribution(g);
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("courbes.dat"))) {
            bw.write("# y\tx\n");
            for (int k = 0; k < distributionDegres.length; k++) {
                if (distributionDegres[k] != 0) {
                    // pk = Nk / N
                    bw.write(k + "\t" + ((double)distributionDegres[k] / N) + "\n");
                }
            }
        }

        // Distance moyenne
        // <d> = 1/(N(N-1))*somme des distances
        // ou <d> = ln N / ln <k>

        double D = Math.log(N) / Math.log(K);
        System.out.println("D = " + D);

        int sommeDistances = 0;
        int paireCompter = 0; // nombre de paires (source, cible) effectivement prises en compte
        int distanceMax = 500;
        long[] distributionDistances = new long[distanceMax];

        // 1000 sommets choisis au hasards
        for (Node source : Toolkit.randomNodeSet(g, 1000)) {
            BreadthFirstIterator it = new BreadthFirstIterator(source);

            while (it.hasNext()) {
                Node u = it.next();
                int distance = it.getDepthOf(u);  // distance en nombre d'arêtes depuis 'source' jusqu'à 'u'

                sommeDistances += distance;
                paireCompter++;

                if (distance > 0) {
                    distributionDistances[distance]++;
                }
            }
        }

        // moyenne sur toutes les paires (source, cible) explorées
        double moyenneDistances = (double) sommeDistances / paireCompter;

        System.out.println("Distance moyenne : " + moyenneDistances);

        long totalPourDistribution = 0L;
        for (int d = 1; d <= distanceMax; d++) {
            totalPourDistribution += distributionDistances[d];
        }

        try (BufferedWriter bw = new BufferedWriter(new FileWriter("distances.dat"))) {
            bw.write("# d\tp(d)\n");
            for (int d = 1; d <= distanceMax; d++) {
                if (distributionDistances[d] > 0) {
                    double proba = distributionDistances[d] / (double) totalPourDistribution;
                    bw.write(d + "\t" + proba + "\n");
                }
            }
        }
    }
}