// wrenEngine.c -- bridges the Wren adapter to the actor layer's CalogEngineT vtable.
//
// Every hook runs on the owning context's thread (createInterpreter, runSource,
// destroyInterpreter), confining the Wren VM to one thread. createInterpreter builds the
// VM (and its Calog dispatcher class) and validates the registered natives; runSource
// evaluates a script and reports failure through the single error channel (result).

#include "calogInternal.h"
#include "wrenAdapter.h"

static int32_t wrenEngineCreate(CalogContextT *context, void **interpOut);
static void    wrenEngineDestroy(void *interp);
static int32_t wrenEngineRun(void *interp, const char *source, CalogValueT *result);
static void    wrenExposeVisitor(const CalogEntryT *entry, void *ud);

static const char *const wrenExtensions[] = { "wren", NULL };

const CalogEngineT calogWrenEngine = {
    "wren",
    wrenExtensions,
    wrenEngineCreate,
    wrenEngineDestroy,
    wrenEngineRun
};


static int32_t wrenEngineCreate(CalogContextT *context, void **interpOut) {
    CalogWrenT *wren;
    int32_t     status;

    *interpOut = NULL;
    status = calogWrenCreate(&wren, calogContextBroker(context), calogContextId(context));
    if (status != calogOkE) {
        return status;
    }
    calogForEach(calogContextBroker(context), wrenExposeVisitor, wren);
    *interpOut = wren;
    return calogOkE;
}


static void wrenEngineDestroy(void *interp) {
    calogWrenDestroy((CalogWrenT *)interp);
}


static int32_t wrenEngineRun(void *interp, const char *source, CalogValueT *result) {
    int32_t status;

    calogValueNil(result);
    status = calogWrenRun((CalogWrenT *)interp, source);
    if (status != calogOkE) {
        return calogFail(result, status, "wren script failed");
    }
    return calogOkE;
}


static void wrenExposeVisitor(const CalogEntryT *entry, void *ud) {
    calogWrenExpose((CalogWrenT *)ud, entry->name);
}
