#pragma once
#include <asio/awaitable.hpp>
#include <asio/co_spawn.hpp>
#include <asio/executor_work_guard.hpp>
#include <asio/io_context.hpp>
#include <asio/thread_pool.hpp>
#include <asio/use_future.hpp>
#include <atomic>
#include <chrono>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include "asio/bind_executor.hpp"
#include "private_psc_global_include/Singleton.hpp"
class Coro : public Psc::Singleton<Coro> {
public:
    void start();
    void stop();
    asio::awaitable<void> sleep_for(std::chrono::milliseconds ms);
    asio::io_context io;
    std::unique_ptr<asio::thread_pool> process_data;
    template <typename Awaitable>
    std::shared_ptr<std::future<void>> spawn(Awaitable&& awaitable) {
        auto future = asio::co_spawn(io, std::forward<Awaitable>(awaitable), asio::use_future);
        return std::make_shared<std::future<void>>(std::move(future));
    }
    // template<typename Awaitable>
    // void spawn(Awaitable &&awaitable) {
    // 	asio::co_spawn(io, std::forward<Awaitable>(awaitable), [](std::exception_ptr exception) {
    // 		if (exception) {
    // 			std::rethrow_exception(exception);
    // 		}
    // 	});
    // }
private:
    asio::awaitable<void> coro_thread();
    std::unique_ptr<asio::executor_work_guard<asio::io_context::executor_type>> io_work;
    std::thread io_thread;
    std::unique_ptr<std::future<void>> loop_task;
    std::atomic<bool> running = false;
};
inline asio::awaitable<void> resume_on(asio::any_io_executor ex) {
    co_await asio::post(asio::bind_executor(ex, asio::deferred));
}
inline asio::awaitable<void> dispatch_on(asio::any_io_executor ex) {
    co_await asio::dispatch(asio::bind_executor(ex, asio::deferred));
}
