#pragma once

#include <memory>
#include <vector>

struct Command;
class ReplayRecorder;
class Simulation;

// Ordered queue that funnels every player command into the single
// Simulation::apply chokepoint (see docs/replay_design.md). This is deliberately
// NOT the EventManager pub/sub bus: sim mutations must apply in a strict,
// tick-pinned, recordable order to a single recipient.
//
// Live play pushes commands via enqueue(); they are applied at the next drain(),
// which runs once per frame before the tick batch. Draining before the tick
// (even at 0x game speed) lets a paused player see placed construction sites
// immediately while staying deterministic — replay applies each command at its
// recorded tick regardless of frame cadence.
class CommandManager
{
public:
    explicit CommandManager(Simulation& simulation);
    // Defined out-of-line so the unique_ptr<ReplayRecorder> member can be
    // destroyed where ReplayRecorder is a complete type.
    ~CommandManager();

    // Append a command for application at the next drain (FIFO order).
    void enqueue(std::shared_ptr<const Command> command);

    // Apply all queued commands in FIFO order through Simulation::apply, then
    // clear the queue. If a recorder is attached, each applied command is recorded
    // (a Reset rolls the recorder to a new file).
    void drain();

    bool hasPending() const;

    // Attach a recorder and start recording the current run. Ownership is taken.
    // Passing nullptr detaches/stops recording.
    void setRecorder(std::unique_ptr<ReplayRecorder> recorder);

    // In replay mode, enqueue() is a no-op: the queue is driven by the recorded
    // stream (ReplayPlayer), so stray live input produces nothing.
    void setReplayMode(bool replayMode);

    // Record a periodic RNG checksum if the current tick is on the checksum
    // cadence. Call once per simulated tick (from the tick loop).
    void recordTickCheckpoint();

private:
    Simulation&                                 m_simulation;
    std::vector<std::shared_ptr<const Command>> m_queue;
    std::unique_ptr<ReplayRecorder>             m_recorder;
    bool                                        m_replayMode = false;
};
