#pragma once

#include "foundation/result.h"

#include <cstddef>
#include <cstdint>
#include <deque>

namespace pp::foundation {

constexpr std::size_t max_task_queue_entries = 65536;

using TaskCallback = void (*)(void* user_data) noexcept;

struct TaskItem {
    TaskCallback callback = nullptr;
    void* user_data = nullptr;
    std::uint64_t id = 0;
};

class TaskQueue {
public:
    explicit TaskQueue(std::size_t max_entries = max_task_queue_entries) noexcept;

    [[nodiscard]] std::size_t size() const noexcept;
    [[nodiscard]] bool empty() const noexcept;
    [[nodiscard]] std::size_t max_entries() const noexcept;

    [[nodiscard]] Status push(TaskItem task);
    [[nodiscard]] Result<TaskItem> pop() noexcept;
    [[nodiscard]] Status run_next() noexcept;
    [[nodiscard]] std::size_t run_all() noexcept;
    void clear() noexcept;

private:
    std::size_t max_entries_ = max_task_queue_entries;
    std::deque<TaskItem> tasks_;
};

}
