//
// Created by Lenn on 2025/10/31.
//

#ifndef TOUCHSENSOR_PRESIST_HH
#define TOUCHSENSOR_PRESIST_HH

#include <atomic>
#include <condition_variable>
#include <deque>
#include <future>
#include <memory>
#include <mutex>
#include <queue>
#include <string>
#include <thread>

namespace ffmsep {

struct DecodedFrame;

namespace persist {

struct WriteResult {
    bool ok = false;
    std::string error;
    std::string path;
};

struct WriteRequest {
    WriteRequest() = default;
    WriteRequest(std::string p,
                 std::deque<std::shared_ptr<DecodedFrame>> f,
                 std::promise<WriteResult>&& pr)
        : path(std::move(p))
        , frames(std::move(f))
        , promise(std::move(pr)) {}

    WriteRequest(const WriteRequest&) = delete;
    WriteRequest& operator=(const WriteRequest&) = delete;
    WriteRequest(WriteRequest&&) noexcept = default;
    WriteRequest& operator=(WriteRequest&&) noexcept = default;

    std::string path;
    std::deque<std::shared_ptr<DecodedFrame>> frames;
    std::promise<WriteResult> promise;
};

class WriteQueue {
public:
    bool push(WriteRequest&& req);
    bool pop(WriteRequest& out);
    void stop();

private:
    std::mutex mutex_;
    std::condition_variable cond_;
    std::queue<WriteRequest> queue_;
    bool stopped_ = false;
};

class JsonWritter {
public:
    JsonWritter();
    ~JsonWritter();

    std::future<WriteResult> enqueue(std::string path,
                                     std::deque<std::shared_ptr<DecodedFrame>> frames);

    void stop();

private:
    void run();
    WriteResult write_once(const std::string& path,
                           std::deque<std::shared_ptr<DecodedFrame>> frames);

private:
    std::thread write_thread_;
    WriteQueue write_queue_;
    std::atomic_bool stopped_{false};
};

} // namespace persist
} // namespace ffmsep

#endif // TOUCHSENSOR_PRESIST_HH
