#pragma once

#include <stdint.h>

#include <enkiTS/TaskScheduler.h>

// callback for crTasks::ParallelFor. it runs on a worker thread and receives a slice of [0, count):
// write only to what the slice owns, or the result stops being reproducible.
// threadIndex is enki's, bounded by crTasks::WORKER_COUNT — the natural key for per-thread tallies
// that would otherwise need atomics
typedef void crParallelForFn( int32_t begin, int32_t end, uint32_t threadIndex, void* context );

// shared enkiTS scheduler; one worker pool serves box3d + ECS
// (WASM PTHREAD_POOL_SIZE budgets for exactly one pool — do not create another scheduler)
struct crTasks
{
    static constexpr int32_t WORKER_COUNT = 4;

    inline static enki::TaskScheduler scheduler;

    // fan [0, count) over the pool in slices of at least minRange, and WAIT for all of it.
    //
    // a function pointer and a void* rather than a callable: the codebase already passes callbacks
    // this way (devConsole, box3d), and it keeps the adapter free of allocation and type erasure.
    // the task object lives on THIS call's stack, so nesting and recursion are safe — a shared
    // static instance would corrupt itself the moment two fan-outs overlapped
    static void ParallelFor( int32_t count, uint32_t minRange, crParallelForFn* fn, void* context )
    {
        if( count <= 0 )
            return;

        Adapter adapter;
        adapter.fn        = fn;
        adapter.context   = context;
        adapter.m_SetSize  = static_cast<uint32_t>( count );
        adapter.m_MinRange = minRange;

        scheduler.AddTaskSetToPipe( &adapter );
        scheduler.WaitforTask( &adapter );
    }

private:
    struct Adapter : public enki::ITaskSet
    {
        crParallelForFn* fn      = nullptr;
        void*            context = nullptr;

        void ExecuteRange( enki::TaskSetPartition range, uint32_t threadIndex ) override
        {
            fn( static_cast<int32_t>( range.start ), static_cast<int32_t>( range.end ), threadIndex, context );
        }
    };
};
