#pragma once
#include <asio/awaitable.hpp>
#include <atomic>
#include <chrono>
#include <exception>
#include <format>
#include <future>
#include <iostream>
#include <memory>
#include <sstream>
#include <string_view>
#include <thread>
#include <utility>
#include <vector>
#include "Psc_Cpp_Core/Base/JSON.h"
#include "Psc_Cpp_Core/Statistics/Frequency_Limit.h"
#include "adminive/managed.hpp"
struct With_Loop_Coro_Config {
    bool enable{};
    PSC_USE_JSON
};
namespace adminive {
template <>
struct Type_Descriptor<With_Loop_Coro_Config> {
    static auto get() {
        using T = With_Loop_Coro_Config;
        return object<T>("with_loop_coro_config", "运行配置", ADMINIVE_FIELD_LABEL(T, enable, "启用").editable().boolean_input());
    }
};
}
class With_Loop_Coro {
public:
    virtual ~With_Loop_Coro();
    std::string type;
    std::string key;
    adminive::Managed_Value<With_Loop_Coro_Config> config;
    std::shared_ptr<std::future<void>> loop_task;
    virtual asio::awaitable<void> loop_coro() = 0;
    void async_stop();
    void sync_wait();
    [[nodiscard]] bool running() const;
    [[nodiscard]] bool enabled() const {
        return config.member<&With_Loop_Coro_Config::enable>().read([](bool value) {
            return value;
        });
    }
    void set_enabled(bool value) {
        config.member<&With_Loop_Coro_Config::enable>().write([value](bool& target) {
            target = value;
        });
    }
    [[nodiscard]] Psc::JSON to_base_json() const {
        auto ret = config.read([](const auto& value) {
            return value.to_base_json();
        });
        ret.append({"type", type});
        ret.append({"key", key});
        return ret;
    }
    void from_base_json(const Psc::JSON* that_json, bool not_exist_use_default_value) {
        Get_J(type) Get_J(key)
        config.write([&](auto& value) {
            value.from_base_json(that_json, not_exist_use_default_value);
        });
    }
    asio::awaitable<void> tick();
    virtual asio::awaitable<void> _open() = 0;
    virtual asio::awaitable<void> _close() = 0;
    enum class State {
        Force_Quit,
        Start,
        Before_Request_Start_Loop,
        Waiting_Loop_Start,
        Loop_Running,
        Loop_Exception,
        Before_Request_Stop_Loop,
        Waiting_Stop_Loop
    } state = State::Start;
    void set_state(State state, std::string_view action = "");
    With_Loop_Coro();
protected:
    Psc::Copyable_Atomic<bool> loop_running{};
    asio::awaitable<void> run_loop_coro();
    Frequency_Limit_Multi stop;
};
