package fr.univ.dblp.loader;

import org.graphstream.graph.Graph;
import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.stream.file.FileSourceEdge;

import java.io.IOException;

/**
 * Classe utilitaire pour charger des graphes depuis des fichiers.
 *
 * Cette classe gère le chargement du réseau de collaboration DBLP
 * depuis un fichier au format liste d'arêtes.
 *
 * @author Hamadou BA
 * @see <a href="https://www-apps.univ-lehavre.fr/forge/bh243413/tp2-ri-mesures-de-reseaux-interaction.git">Dépôt Git</a>
 */
public class GraphLoader {

    /**
     * Charge le réseau de collaboration DBLP depuis un fichier.
     *
     * Utilise FileSourceEdge de GraphStream pour lire le fichier au format
     * liste d'arêtes (chaque ligne contient deux identifiants de nœuds).
     *
     * @param filePath Chemin vers le fichier de données DBLP
     * @return Le graphe chargé, ou null si le chargement a échoué
     */
    public static Graph loadDBLP(String filePath) {
        System.out.println("\n[CHARGEMENT] Lecture du graphe DBLP depuis: " + filePath);

        Graph graph = new SingleGraph("DBLP");
        configureGraph(graph);

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

        try {
            long startTime = System.currentTimeMillis();
            fs.readAll(filePath);
            long elapsed = System.currentTimeMillis() - startTime;

            System.out.printf("  Graphe chargé avec succès en %.2f secondes%n", elapsed / 1000.0);
            displayGraphInfo(graph);

            return graph;
        } catch (IOException e) {
            System.err.println("  [ERREUR] Impossible de charger le graphe: " + e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            fs.removeSink(graph);
        }
    }

    /**
     * Configure les propriétés du graphe.
     *
     * Active la création automatique de nœuds lors de la lecture des arêtes
     * et configure le mode non-strict pour gérer les multi-arêtes.
     *
     * @param graph Le graphe à configurer
     */
    private static void configureGraph(Graph graph) {
        // Ne pas créer d'arêtes multiples entre les mêmes nœuds
        graph.setStrict(false);
        // Création automatique des nœuds quand les arêtes les référencent
        graph.setAutoCreate(true);
    }

    /**
     * Affiche les informations de base sur le graphe chargé.
     *
     * Affiche le nombre de nœuds, d'arêtes et le type de graphe
     * (dirigé ou non dirigé).
     *
     * @param graph Le graphe dont on affiche les informations
     */
    public static void displayGraphInfo(Graph graph) {
        System.out.println("\n[INFORMATION DU GRAPHE]");
        System.out.printf("  Nombre de nœuds  : %,d%n", graph.getNodeCount());
        System.out.printf("  Nombre d'arêtes  : %,d%n", graph.getEdgeCount());
        // Note: SingleGraph est toujours non dirigé
        System.out.printf("  Graphe dirigé    : %s%n", "Non");
    }
}
