#include <epictuner/sdk/jobs.hpp>
#include <chrono>
#include <cstring>
#include <optional>
#include <thread>

class Background : public et::sdk::Plugin {
    std::optional<et::sdk::Context> host_;
    et::sdk::Jobs jobs_;
    et_handle job_{};
    bool completed_ = false;
    static et_result ET_CALL work(void*, const et_job_control* control, et_job_output* output)
    {
        // Synthetic calculation. Probe cancellation between bounded chunks.
        uint32_t sum = 0;
        for (uint32_t i = 1; i <= 10; ++i) {
            if (control->is_cancelled(control->context)) return ET_ERROR_CANCELLED;
            sum += i;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        if (sum != 55) return ET_ERROR_STATE;
        const char text[] = "background sum=55";
        std::memcpy(output->data, text, sizeof(text) - 1);
        output->size = sizeof(text) - 1;
        return ET_OK;
    }
    static void ET_CALL complete(void* context, const et_completion* completion)
    {
        auto& self = *static_cast<Background*>(context);
        self.completed_ = true;
        if (completion->code == ET_OK) {
            const auto& bytes = completion->value.data.bytes;
            self.host_->log({reinterpret_cast<const char*>(bytes.data), bytes.size});
        } else self.host_->log("background cancelled");
    }
public:
    static constexpr std::string_view id = "org.epictuner.examples.background";
    static constexpr uint64_t capabilities = ET_CAP_LOG | ET_CAP_EVENTS | ET_CAP_JOBS;
    et_result start(et::sdk::Context& context)
    {
        host_ = context;
        const auto result = jobs_.connect(context);
        if (result != ET_OK) return result;
        const et_async_options options{sizeof(et_async_options), 2000, 0, 0, this, complete};
        return jobs_.submit(work, nullptr, options, job_);
    }
    et_result onEvent(const et_event& event)
    {
        if (std::string_view(event.text.data, event.text.size) == "cancel") return jobs_.cancel(job_);
        return host_->log("background event received");
    }
    et_result stop()
    {
        if (!completed_) return ET_ERROR_STATE;
        return host_->log("background stopped after completion");
    }
};
ET_PLUGIN(Background)
