import org.graphstream.algorithm.generator.BarabasiAlbertGenerator;
import org.graphstream.algorithm.generator.Generator;
import org.graphstream.algorithm.generator.RandomGenerator;
import org.graphstream.graph.BreadthFirstIterator;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.stream.file.FileSource;
import org.graphstream.stream.file.FileSourceEdge;

import static org.graphstream.algorithm.Toolkit.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class AnalyseRI {

    public static void main(String[] args) throws IOException {
        Graph g = new DefaultGraph("g");
        FileSource fs = new FileSourceEdge();

        fs.addSink(g);

        try {
            fs.readAll("/home/bryan/IdeaProjects/TP2/src/fichier.txt");
        } catch( IOException e) {e.printStackTrace();}
        System.out.println("Nombre de noeud : "+g.getNodeCount());
        System.out.println("Nombre de liens : "+g.getEdgeCount());
        System.out.println("Degres moyen : "+averageDegree(g));
        System.out.println("Coefficient de Clustering : "+averageClusteringCoefficient(g));
        System.out.println(averageDegree(g)/g.getNodeCount());
        System.out.println(isConnected(g));
        System.out.println(averageDegree(g)*2>Math.log(g.getNodeCount()));
        System.out.println(Arrays.toString(degreeDistribution(g)));

        ArrayList<Node> echantillon = new ArrayList<Node>();
        for(int i = 0 ; i < 1000 ; i++) {
            int random = (int) (Math.random() * g.getNodeCount());
            Node noeud = g.getNode(random);
            while( echantillon.contains(noeud) ) noeud = g.getNode((int) (Math.random() * g.getNodeCount()));
            echantillon.add(noeud);
        }
        System.out.println("Noeuds aléatoires trouvées");
        ArrayList<Integer> chemins = new ArrayList<Integer>();
        for ( int i = 0 ; i < echantillon.size() ; i++ ) {
            Node noeud = echantillon.get(i);
            BreadthFirstIterator it = new BreadthFirstIterator(noeud);
            for( int j = i+1 ; j < echantillon.size() ; j++ ) {
                Node noeud2 = echantillon.get(j);
                while( it.hasNext() && ! it.next().equals(noeud2) ) {}
                chemins.add(it.getDepthOf(noeud2));
            }
            System.out.println("Noeud " + i + " calculé");
        }
        System.out.println("Chemins calculées");
        int nb = chemins.size();
        int somme = 0;

        Map<Integer, Float> map = new HashMap<>();

        for( Integer d : chemins ) {
            somme+= d;
            if(map.containsKey(d)) {
                map.put(d, map.get(d) + 1);
            } else {
                map.put(d, 1f);
            }
        }
        for (Integer i : map.keySet()) {
            map.put(i, map.get(i) / nb);
            System.out.print(i);
            System.out.print(" ");
            System.out.println(map.get(i));
        }

        System.out.println("somme = " + somme + " | nb = " + nb);
        System.out.println("Longeur moyenne = " + (1.0 *somme/nb));

        // Question 6
        Generator gen1 = new RandomGenerator(averageDegree(g));
        Generator gen2 = new BarabasiAlbertGenerator(6);
        System.out.println("Graphe aléatoire : ");
        testGenerator(gen1, g);
        System.out.println("Graphe Barabasi-Albert : ");
        testGenerator(gen2, g);

    }

    public static void testGenerator(Generator gen, Graph g) {
        int nb = 0;
        int somme = 0;
        ArrayList<Node> echantillon;
        ArrayList<Integer> chemins;
        Graph graph = new SingleGraph("Random");

        gen.addSink(graph);
        gen.begin();
        nb = g.getNodeCount();
        for(int i=0; i < nb; i++)
            gen.nextEvents();
        gen.end();

        //System.out.println("Graphe aléatoire : ");
        System.out.println("Nombre de noeuds          : " + graph.getNodeCount());
        System.out.println("Nombre de liens           : " + graph.getEdgeCount());
        System.out.println("Degre moyen               : " + averageDegree(graph));
        System.out.println("Coefficient de clustering : " + averageClusteringCoefficient(graph));
        System.out.println("le graphe est connexe : " +  isConnected(graph) );

        echantillon = new ArrayList<Node>();
        for(int i = 0 ; i < 1000 ; i++) {
            int random = (int) (Math.random() * graph.getNodeCount());
            Node noeud = graph.getNode(random);
            while( echantillon.contains(noeud) ) noeud = graph.getNode((int) (Math.random() * graph.getNodeCount()));
            echantillon.add(noeud);
        }
        chemins = new ArrayList<Integer>();
        for ( int i = 0 ; i < echantillon.size() ; i++ ) {
            Node noeud = echantillon.get(i);
            BreadthFirstIterator it = new BreadthFirstIterator(noeud);
            for( int j = i+1 ; j < echantillon.size() ; j++ ) {
                Node noeud2 = echantillon.get(j);
                while( it.hasNext() && ! it.next().equals(noeud2) ) {}
                chemins.add(it.getDepthOf(noeud2));
            }
        }
        nb = chemins.size();
        for( Integer d : chemins ) somme+= d;
        System.out.println("somme = " + somme + " | nb = " + nb);
        System.out.println("Longeur moyenne = " + (1.0 *somme/nb));

    }
}
