package iwocs;

import java.io.FileNotFoundException;
import java.util.Scanner;

import org.graphstream.algorithm.Toolkit;
import org.graphstream.graph.Graph;

import iwocs.graphs.GraphIO;
import iwocs.graphs.GraphUtils;
import iwocs.graphs.propagation.ImmunizationMethod;
import iwocs.graphs.propagation.SelectiveImmunization;

/**
 * App which purpose is to experiment on a real life scaled interaction network
 * (scientific collaboration).
 */
public class App {
  public static void main(String[] args) {
    Graph g1 = GraphIO.getNerdsGraph();
    GraphUtils.randomlyImmunize(g1, 0.5, ImmunizationMethod.NODE);
    GraphIO.exportDegreeDistribution(g1, "data/propagation/node_immune_degree_distribution", true);

    Graph g2 = GraphIO.getNerdsGraph();
    GraphUtils.randomlyImmunize(g2, 0.5, ImmunizationMethod.EDGE);
    GraphIO.exportDegreeDistribution(g2, "data/propagation/edge_immune_degree_distribution", true);

    // Dirty scan to wait for the comma decimals to be changed manually to points (yep)
    try(Scanner sc = new Scanner(System.in)) {
      System.out.println("CHANGE LES DONNEES VITE");
      sc.nextLine();
      sc.close();
    }

    try {
      System.out.printf("λc(node): %.3f\n", Toolkit.averageDegree(g1) / GraphUtils.calculateVarianceFromDistribution("data/propagation/node_immune_degree_distribution", false));
      System.out.printf("λc(edge): %.3f\n", Toolkit.averageDegree(g2) / GraphUtils.calculateVarianceFromDistribution("data/propagation/edge_immune_degree_distribution", false));
    } catch(FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  public static void showMeanDegreesOfGroups0And1() {
    Graph g = GraphIO.getNerdsGraph();

    SelectiveImmunization immunization = GraphUtils.getSelectiveImmunizationGroups(g, 0.5);

    System.out.printf(
      "G0: %.3f, G1: %.3f\n",
      GraphUtils.meanDegreeOfNodeSet(immunization.getGroup0()),
      GraphUtils.meanDegreeOfNodeSet(immunization.getGroup1())
    );
  }

  public static void simulatePropagationCases() {
    double beta = 1.0 / 7.0, mu = 1.0 / 14.0;
    int n = 3 * 4 * 7;

    Graph g = GraphIO.getNerdsGraph();
    GraphUtils.simulatePropagation(g, "infected", beta, mu, n).export("data/propagation/no_immune_graph");

    GraphUtils.randomlyImmunize(g, 0.5, ImmunizationMethod.NODE);
    GraphUtils.makePatientZero(g, "infected");
    GraphUtils.simulatePropagation(g, "infected", beta, mu, n).export("data/propagation/node_immune_graph");

    Graph g1 = GraphIO.getNerdsGraph();
    GraphUtils.randomlyImmunize(g1, 0.5, ImmunizationMethod.EDGE);
    GraphUtils.simulatePropagation(g1, "infected", beta, mu, n).export("data/propagation/edge_immune_graph");
  }

  public static void displayGraphVariance() {
    try {
      System.out.printf("Variance : %f\n",
          GraphUtils.calculateVarianceFromDistribution("data/nerds_degrees_distrib", false));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static void analyzeGraphs() {
    Graph g = GraphIO.getNerdsGraph();

    System.out.println("Nerds graph:");
    System.out.format("N: %d\nL: %d\n<k>: %.3f\n<C>: %.3f\nConnected: %b\n<d>: %.3f\n", g.getNodeCount(),
        g.getEdgeCount(), Toolkit.averageDegree(g), Toolkit.averageClusteringCoefficient(g), Toolkit.isConnected(g),
        GraphUtils.calculateMeanDistanceFromSample(g, 1000));

    // export degree distribution
    GraphIO.exportDegreeDistribution(g, "data/nerds_degrees_distrib", true);

    // export distances distribution
    GraphIO.exportHashMapDistribution(GraphUtils.calculateDistancesDistributionFromSample(g, 1000, true),
        "data/nerds_distances_distrib");

    Graph random = GraphUtils.getRandomGraph("random", g.getNodeCount(), Toolkit.averageDegree(g));

    System.out.println("\nRandom graph:");
    System.out.format("N: %d\nL: %d\n<k>: %.3f\n<C>: %.3f\nConnected: %b\n<d>: %.3f\n", random.getNodeCount(),
        random.getEdgeCount(), Toolkit.averageDegree(random), Toolkit.averageClusteringCoefficient(random),
        Toolkit.isConnected(random), GraphUtils.calculateMeanDistanceFromSample(random, 1000));

    // export degree distribution
    GraphIO.exportDegreeDistribution(random, "data/random_degrees_distrib", true);

    // export distances distribution
    GraphIO.exportHashMapDistribution(GraphUtils.calculateDistancesDistributionFromSample(random, 1000, true),
        "data/random_distances_distrib");

    Graph preferential = GraphUtils.getPreferentialGraph("preferential", g.getNodeCount(), Toolkit.averageDegree(g));

    System.out.println("\nPreferential graph:");
    System.out.format("N: %d\nL: %d\n<k>: %.3f\n<C>: %.3f\nConnected: %b\n<d>: %.3f\n", preferential.getNodeCount(),
        preferential.getEdgeCount(), Toolkit.averageDegree(preferential),
        Toolkit.averageClusteringCoefficient(preferential), Toolkit.isConnected(preferential),
        GraphUtils.calculateMeanDistanceFromSample(preferential, 1000));

    // export degree distribution
    GraphIO.exportDegreeDistribution(preferential, "data/preferential_degrees_distrib", true);

    // export distances distribution
    GraphIO.exportHashMapDistribution(GraphUtils.calculateDistancesDistributionFromSample(preferential, 1000, true),
        "data/preferential_distances_distrib");
  }
}