package sd.dashboard;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import sd.model.VehicleType;

/**
 * Objeto de Transferência de Dados (DTO) otimizado para transporte de telemetria.
 * <p>
 * Esta classe encapsula as métricas de desempenho enviadas pelos nós da simulação (Coordenador,
 * Interseções, ExitNode) para o Dashboard. Foi desenhada para suportar <b>atualizações parciais</b>
 * (Sparse Updates):
 * <ul>
 * <li>Campos globais inicializados com {@code -1} indicam "sem alteração" (no-op). O Dashboard
 * deve ignorar estes campos e manter o valor acumulado anterior.</li>
 * <li>Campos de interseção ({@code arrivals}, {@code departures}) representam deltas ou snapshots
 * específicos do nó remetente.</li>
 * </ul>
 * Implementa {@link Serializable} para transmissão direta via Java Sockets.
 * 

[Image of data transfer object pattern]

 */
public class StatsUpdatePayload implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // Global Metrics (Coordinator/ExitNode)
    /** Total gerado. Valor -1 indica que este campo deve ser ignorado na atualização. */
    private int totalVehiclesGenerated = -1;
    
    /** Total completado. Valor -1 indica que este campo deve ser ignorado. */
    private int totalVehiclesCompleted = -1;
    
    /** Tempo total de sistema acumulado (ms). Valor -1 indica que deve ser ignorado. */
    private long totalSystemTime = -1;
    
    /** Tempo total de espera acumulado (ms). Valor -1 indica que deve ser ignorado. */
    private long totalWaitingTime = -1;
    
    // Intersection Metrics (Worker Nodes)
    /** Número de veículos que entraram na interseção desde o último reporte. */
    private int intersectionArrivals = 0;
    
    /** Número de veículos que saíram da interseção desde o último reporte. */
    private int intersectionDepartures = 0;
    
    /** Snapshot do tamanho atual da fila na interseção. */
    private int intersectionQueueSize = 0;
    
    // Detailed Breakdowns
    /** Contagem acumulada por tipo de veículo. */
    private Map<VehicleType, Integer> vehicleTypeCounts;
    
    /** Tempos de espera acumulados por tipo de veículo. */
    private Map<VehicleType, Long> vehicleTypeWaitTimes;
    
    /**
     * Inicializa o payload com os mapas vazios e contadores globais a -1 (estado neutro).
     */
    public StatsUpdatePayload() {
        this.vehicleTypeCounts = new HashMap<>();
        this.vehicleTypeWaitTimes = new HashMap<>();
    }
    
    public int getTotalVehiclesGenerated() {
        return totalVehiclesGenerated;
    }
    
    public int getTotalVehiclesCompleted() {
        return totalVehiclesCompleted;
    }
    
    public long getTotalSystemTime() {
        return totalSystemTime;
    }
    
    public long getTotalWaitingTime() {
        return totalWaitingTime;
    }
    
    public int getIntersectionArrivals() {
        return intersectionArrivals;
    }
    
    public int getIntersectionDepartures() {
        return intersectionDepartures;
    }
    
    public int getIntersectionQueueSize() {
        return intersectionQueueSize;
    }
    
    public Map<VehicleType, Integer> getVehicleTypeCounts() {
        return vehicleTypeCounts;
    }
    
    public Map<VehicleType, Long> getVehicleTypeWaitTimes() {
        return vehicleTypeWaitTimes;
    }
    
    // Setters implementam Fluent Interface para construção encadeada
    
    public StatsUpdatePayload setTotalVehiclesGenerated(int totalVehiclesGenerated) {
        this.totalVehiclesGenerated = totalVehiclesGenerated;
        return this;
    }
    
    public StatsUpdatePayload setTotalVehiclesCompleted(int totalVehiclesCompleted) {
        this.totalVehiclesCompleted = totalVehiclesCompleted;
        return this;
    }
    
    public StatsUpdatePayload setTotalSystemTime(long totalSystemTime) {
        this.totalSystemTime = totalSystemTime;
        return this;
    }
    
    public StatsUpdatePayload setTotalWaitingTime(long totalWaitingTime) {
        this.totalWaitingTime = totalWaitingTime;
        return this;
    }
    
    public StatsUpdatePayload setIntersectionArrivals(int intersectionArrivals) {
        this.intersectionArrivals = intersectionArrivals;
        return this;
    }
    
    public StatsUpdatePayload setIntersectionDepartures(int intersectionDepartures) {
        this.intersectionDepartures = intersectionDepartures;
        return this;
    }
    
    public StatsUpdatePayload setIntersectionQueueSize(int intersectionQueueSize) {
        this.intersectionQueueSize = intersectionQueueSize;
        return this;
    }
    
    public StatsUpdatePayload setVehicleTypeCounts(Map<VehicleType, Integer> vehicleTypeCounts) {
        this.vehicleTypeCounts = vehicleTypeCounts;
        return this;
    }
    
    public StatsUpdatePayload setVehicleTypeWaitTimes(Map<VehicleType, Long> vehicleTypeWaitTimes) {
        this.vehicleTypeWaitTimes = vehicleTypeWaitTimes;
        return this;
    }
    
    @Override
    public String toString() {
        return String.format("StatsUpdatePayload[generated=%d, completed=%d, arrivals=%d, departures=%d, queueSize=%d]",
            totalVehiclesGenerated, totalVehiclesCompleted, intersectionArrivals, 
            intersectionDepartures, intersectionQueueSize);
    }
}