#pragma once

#include <cstddef>
#include <optional>
#include <vector>

#include "ReplayReader.h"
#include "Tick.h"

class Simulation;

// Drives playback of a parsed replay against a Simulation: applies each recorded
// command at its recorded tick (through Simulation::apply) and verifies the RNG
// checksums, reporting the first desync. Entries are consumed in file order,
// which reproduces the exact command/tick interleaving of the original run.
//
// Cadence (mirrors how the run was recorded so checksums line up):
//   player.start();                 // process tick-0 entries before the first tick
//   each frame, for each tick to run:
//       if (player.isFinished()) break;
//       sim.tick();
//       player.advanceTo(sim.getCurrentTick());
class ReplayPlayer
{
public:
    ReplayPlayer(Simulation& simulation, std::vector<ReplayEntry> entries);

    // Process all entries recorded at tick 0 (the initial checksum and any
    // commands issued before the first tick). Call once, before the first tick.
    void start();

    // Process all entries recorded at `tick`. Call once after each sim.tick().
    void advanceTo(Tick tick);

    // True once all entries are consumed or a desync was detected.
    bool isFinished() const;

    // The tick at which the recomputed checksum first diverged, if any.
    std::optional<Tick> getDesyncTick() const;

private:
    void processEntriesAt(Tick tick);

    Simulation&              m_simulation;
    std::vector<ReplayEntry> m_entries;
    std::size_t              m_cursor = 0;
    std::optional<Tick>      m_desyncTick;
};
