#pragma once
#include <atomic>
#include <deque>
#include <functional>
#include <mutex>
#include <thread>
#include <ftxui/component/screen_interactive.hpp>
#include "torlinkc/config/config.hpp"
#include "torlinkc/engine/queue.hpp"
#include "torlinkc/ui/app_state.hpp"
namespace torlinkc::ui {
// Owns the DownloadQueue -- and therefore the libtorrent session -- on a
// dedicated background thread, since neither is safe to touch concurrently
// from the UI thread. The two threads only ever talk in one direction each:
// the UI thread enqueues a command via post(), and the engine thread replies
// (if at all) by posting a state snapshot onto FTXUI's own thread-safe queue
// (ftxui::ScreenInteractive::Post), which runs it on the UI thread. Neither
// side ever reaches across and touches the other's data directly -- see the
// "Concurrency / state model" section of the phased plan.
class EngineThread {
public:
EngineThread(ftxui::ScreenInteractive& screen, AppState& state);
~EngineThread();
EngineThread(const EngineThread&) = delete;
EngineThread& operator=(const EngineThread&) = delete;
// Boots the queue (restore, safe-mode/bootguard handling) and starts
// ticking. Call once, before screen.Loop().
void start(Config config);
// Signals the loop to stop, waits for it to flush state and exit. Safe to
// call from the UI thread after screen.Loop() returns.
void stop();
// Thread-safe: queues `fn` to run against the live DownloadQueue on the
// engine thread's next loop iteration. Use this for anything a keypress
// wants the queue to do (add/pause/resume/...) -- never call DownloadQueue
// methods directly from the UI thread.
void post(std::function<void(DownloadQueue&)> fn);
private:
void run(Config config);
void publishSnapshot(DownloadQueue& queue);
ftxui::ScreenInteractive& screen_;
AppState& state_;
std::thread thread_;
std::atomic<bool> running_{false};
std::mutex commandsMutex_;
std::deque<std::function<void(DownloadQueue&)>> commands_;
};
} // namespace torlinkc::ui