#pragma once

#include <SDL3/SDL.h>

#include <atomic>
#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <thread>

// El Director és el thread principal que controla la presentació i els inputs.
// Executa el joc en un thread secundari (game thread) com si fos una "fibra emulada":
// el joc produeix un frame, es bloqueja a JD8_Flip(), i el director el presenta
// abans de donar-li via per produir el següent.
class Director {
   public:
    static void init();
    static void destroy();
    static auto get() -> Director*;

    // Bucle principal del director. Crida des de main().
    void run();

    // Invocat pel game thread des de JD8_Flip(). Bloqueja fins que el director
    // consumeix el frame i dona via per produir el següent.
    void publishFrame(Uint32* pixels);

    // Demana l'eixida (ex: segona pulsació d'ESC o SDL_QUIT)
    void requestQuit();

    // Consumeix el flag de "tecla polsada" (com l'antic JI_AnyKey)
    auto consumeKeyPressed() -> bool;

    // Indica si ESC està bloquejada (el joc no l'ha de veure)
    auto isEscBlocked() const -> bool { return esc_blocked_ || esc_swallow_until_release_; }

   private:
    Director() = default;
    ~Director() = default;

    static Director* instance_;

    void gameThreadFunc();
    void handleEvents();

    std::thread game_thread_;
    std::mutex mutex_;
    std::condition_variable frame_produced_cv_;
    std::condition_variable frame_consumed_cv_;

    Uint32* latest_frame_{nullptr};
    bool frame_ready_{false};
    bool frame_consumed_{true};

    std::atomic<bool> quit_requested_{false};
    std::atomic<bool> game_thread_done_{false};
    std::atomic<bool> key_pressed_{false};
    std::atomic<bool> esc_blocked_{false};
    // Quan el menú tanca amb ESC, empassem-nos l'ESC fins que l'usuari la deixe anar,
    // per no fer eixir el joc al proper poll de JI_KeyPressed.
    std::atomic<bool> esc_swallow_until_release_{false};
};
