import org.graphstream.algorithm.Toolkit;
import org.graphstream.algorithm.generator.Generator;
import org.graphstream.algorithm.generator.RandomGenerator;
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.FileSource;
import org.graphstream.stream.file.FileSourceEdge;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;

public class Mesures {

    public String valeur = "";

    public String getValeur() {
        return valeur;
    }

    public void setValeur(String valeur) {
        this.valeur = valeur;
    }

    // fonction de génération d'un reseau aleatoire
    public Graph generer_Aleatoire(int taille, double degre) {

        Graph graph = new SingleGraph("Graphe aléatoire");
        System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
        graph.addAttribute("ui.quality");
        graph.addAttribute("ui.antialias");
        Generator g = new RandomGenerator(degre);
        g.addSink(graph);
        g.begin();

        for (int i = 0; i < taille; i++)
            g.nextEvents();
        g.end();
        return graph;
    }

    // Générer des valeurs un fichier
    public void generateData(String nom_fichier) {
        try {
            PrintWriter printWriter = new PrintWriter(nom_fichier, "UTF-8");

            printWriter.write(getValeur());
            printWriter.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }


    }
    // la fonction de génération de distance du reseau de collaboration
    private double distancesReseau(Graph graph, int taille) {
        setValeur("");
        List<Node> sources = Toolkit.randomNodeSet(graph, taille);
        long[] dd = new long[50];
        sources.forEach(source -> {
            BreadthFirstIterator<Node> bf = new BreadthFirstIterator<>(source);
            while (bf.hasNext()) {
                Node v = bf.next();
                dd[bf.getDepthOf(v)]++;
            }
        });
        double dAvg = 0;
        for (int d = 0; d < dd.length; d++) {
            if (dd[d] > 0) {
                double pd = (double) dd[d] / (taille * graph.getNodeCount());
                dAvg += d * pd;


                setValeur(getValeur() + " \n" + d + " " + pd);
                generateData("src/main/resources/file_distributionDistance");
                generateData("src/main/resources/file_distributionDistanceAleatoire");

            }
        }

        return dAvg;
    }

        public static void main(String[] args){
        Mesures mes = new Mesures();
        //lecture fichier
        String filePath = "src/main/resources/com-dblp.ungraph.txt";
        Graph graph = new SingleGraph("g");
        /*graph.addAttribute("ui.quality");
        graph.addAttribute("ui.antialias");
        graph.addAttribute("ui.stylesheet","url('data/design.css')");*/

        FileSource fs = new FileSourceEdge();
        fs.addSink(graph);

        try {
            fs.readAll(filePath);

        } catch (IOException e) {
            e.printStackTrace();
        }

        // Coefficient de clustering
        int noeuds = graph.getNodeCount();
        int liens = graph.getEdgeCount();
        System.out.println("Noeud = " + noeuds);
        System.out.println("Liens = " + liens);
        double degMoyen = Toolkit.averageDegree(graph);
        System.out.println("degré moyen = " + degMoyen);
        System.out.println("coefficient de clustering: " + Toolkit.averageClusteringCoefficient(graph));
        //GenerateurGS_Reseau generateurGS_reseau = new GenerateurGS_Reseau();
        System.out.println("coefficient de clustering pour un réseau aléatoire de la même taille et du même degré moyen est : "
                + Toolkit.averageClusteringCoefficient(mes.generer_Aleatoire(noeuds,
                degMoyen)));
        String message;

        //Connexité
        if (Toolkit.isConnected(graph))
            message = "le réseau est connexe";
        else message = "le réseau n'est pas connexe";
        System.out.println(message);
        System.out.println("Un réseau aléatoire de la même taille et degré moyen " +
                ((Toolkit.isConnected(mes.generer_Aleatoire(noeuds,
                        degMoyen))) ? " est" : "n'est pas") + " connexe");

        // distribution de degre
        int[] dd = Toolkit.degreeDistribution(graph);
        for (int i = 0; i < dd.length; i++) {
            if (dd[i] > 0) {
                System.out.printf("%6d %20f\n", i, (double) dd[i] / noeuds);
                mes.setValeur(mes.getValeur() + " \n" + i + " " + (double) dd[i] / noeuds);
                mes.generateData("src/main/resources/distDegre");

            }

        }

        System.out.println("la distance moyenne dans DBLP = " + mes.distancesReseau(graph, 1000));
        System.out.println("la distance moyenne dans le reseau aléatoire = "
                + Math.log(noeuds)/Math.log(Toolkit.averageDegree(graph)));



    }
}
