package fr.univ.dblp.simulation;

import java.util.List;

/**
 * Résultats d'une simulation de propagation virale.
 * Contient l'évolution temporelle des différents groupes.
 */
public class SimulationResult {
    private final List<Integer> susceptibleOverTime;
    private final List<Integer> infectedOverTime;
    private final List<Integer> immuneCount;
    private final int totalNodes;
    private final int simulationDays;
    private final String scenario;

    public SimulationResult(List<Integer> susceptibleOverTime,
                          List<Integer> infectedOverTime,
                          List<Integer> immuneCount,
                          int totalNodes,
                          int simulationDays,
                          String scenario) {
        this.susceptibleOverTime = susceptibleOverTime;
        this.infectedOverTime = infectedOverTime;
        this.immuneCount = immuneCount;
        this.totalNodes = totalNodes;
        this.simulationDays = simulationDays;
        this.scenario = scenario;
    }

    /**
     * @return Liste du nombre de susceptibles à chaque jour
     */
    public List<Integer> getSusceptibleOverTime() {
        return susceptibleOverTime;
    }

    /**
     * @return Liste du nombre d'infectés à chaque jour
     */
    public List<Integer> getInfectedOverTime() {
        return infectedOverTime;
    }

    /**
     * @return Nombre d'immunisés (constant pendant la simulation)
     */
    public List<Integer> getImmuneCount() {
        return immuneCount;
    }

    /**
     * @return Nombre total de nœuds dans le réseau
     */
    public int getTotalNodes() {
        return totalNodes;
    }

    /**
     * @return Durée de la simulation en jours
     */
    public int getSimulationDays() {
        return simulationDays;
    }

    /**
     * @return Nom du scénario simulé
     */
    public String getScenario() {
        return scenario;
    }

    /**
     * @return Pic d'infection (nombre maximal d'infectés)
     */
    public int getPeakInfection() {
        return infectedOverTime.stream().mapToInt(Integer::intValue).max().orElse(0);
    }

    /**
     * @return Jour où le pic d'infection est atteint
     */
    public int getPeakDay() {
        int peak = getPeakInfection();
        for (int i = 0; i < infectedOverTime.size(); i++) {
            if (infectedOverTime.get(i) == peak) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Calcule la fraction d'infectés parmi la population non immunisée à chaque jour
     * @return Liste des fractions d'infectés (entre 0 et 1)
     */
    public List<Double> getInfectedFractionOverTime() {
        int nonImmune = totalNodes - (immuneCount.isEmpty() ? 0 : immuneCount.get(0));
        return infectedOverTime.stream()
            .map(infected -> nonImmune > 0 ? (double) infected / nonImmune : 0.0)
            .toList();
    }
}
