// calogSquirrelEngine.c -- bridges the Squirrel adapter to the actor CalogEngineT vtable.
//
// Every hook runs on the owning context's thread (createInterpreter, runSource,
// destroyInterpreter), confining the VM to one thread. createInterpreter builds
// the VM and exposes the configured natives; runSource evaluates a script and
// reports failure through the single error channel (result).

#include "calogInternal.h"
#include "squirrelAdapter.h"

static int32_t squirrelEngineCreate(CalogContextT *context, void **interpOut);
static void    squirrelEngineDestroy(void *interp);
static int32_t squirrelEngineRun(void *interp, const char *source, CalogValueT *result);
static void    squirrelExposeVisitor(const CalogEntryT *entry, void *ud);

static const char *const squirrelExtensions[] = { "nut", NULL };

const CalogEngineT calogSquirrelEngine = {
    "squirrel",
    squirrelExtensions,
    squirrelEngineCreate,
    squirrelEngineDestroy,
    squirrelEngineRun
};


static int32_t squirrelEngineCreate(CalogContextT *context, void **interpOut) {
    CalogSquirrelT *sc;
    int32_t         status;

    *interpOut = NULL;
    status = calogSquirrelCreate(&sc, calogContextBroker(context), calogContextId(context));
    if (status != calogOkE) {
        return status;
    }
    calogForEach(calogContextBroker(context), squirrelExposeVisitor, sc);
    *interpOut = sc;
    return calogOkE;
}


static void squirrelExposeVisitor(const CalogEntryT *entry, void *ud) {
    calogSquirrelExpose((CalogSquirrelT *)ud, entry->name);
}


static void squirrelEngineDestroy(void *interp) {
    calogSquirrelDestroy((CalogSquirrelT *)interp);
}


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

    calogValueNil(result);
    status = calogSquirrelRun((CalogSquirrelT *)interp, source);
    if (status != calogOkE) {
        // calogSquirrelRun has already written the detailed diagnostic to stderr;
        // surface a status-bearing error through the single channel.
        return calogFail(result, status, "squirrel script failed");
    }
    return calogOkE;
}
