package sd.des;

/**
 * Gere o tempo de simulação para Simulação de Eventos Discretos.
 * 
 * <p>
 * No DES, o tempo avança em saltos discretos de evento para evento,
 * não de forma contínua como o tempo real.
 * </p>
 * 
 * <p>
 * Esta classe garante que todos os processos no sistema distribuído
 * mantêm uma visão sincronizada do tempo de simulação.
 * </p>
 */
public class SimulationClock {
    private double currentTime;
    private final double startTime;
    private final long wallClockStart;

    public SimulationClock() {
        this(0.0);
    }

    public SimulationClock(double startTime) {
        this.currentTime = startTime;
        this.startTime = startTime;
        this.wallClockStart = System.currentTimeMillis();
    }

    /**
     * Avança o tempo de simulação para o timestamp dado.
     * O tempo só pode avançar, nunca recuar.
     * 
     * @param newTime novo tempo de simulação
     * @throws IllegalArgumentException se newTime for anterior ao tempo atual
     */
    public void advanceTo(double newTime) {
        if (newTime < currentTime) {
            throw new IllegalArgumentException(
                    String.format("Cannot move time backwards: %.3f -> %.3f", currentTime, newTime));
        }
        this.currentTime = newTime;
    }

    /** @return tempo atual da simulação */
    public double getCurrentTime() {
        return currentTime;
    }

    /** @return tempo de simulação decorrido desde o início */
    public double getElapsedTime() {
        return currentTime - startTime;
    }

    /** @return tempo real decorrido em milissegundos */
    public long getWallClockElapsed() {
        return System.currentTimeMillis() - wallClockStart;
    }

    /** Reinicia o relógio para o tempo inicial */
    public void reset() {
        this.currentTime = startTime;
    }

    @Override
    public String toString() {
        return String.format("SimulationClock[time=%.3fs, elapsed=%.3fs]",
                currentTime, getElapsedTime());
    }
}
