#include "qjs_spline.h"
#include "qjs_macros.h"
#include "jsffi.h"
#include "spline.h"
#include "HandmadeMath.h"
#include "stb_ds.h"

// Helper functions - these are duplicated from jsffi.c as they're used there too
static HMM_Vec2 *js2cpvec2arr(JSContext *js, JSValue v) {
  HMM_Vec2 *arr = NULL;
  int n = JS_ArrayLength(js, v);
  arrsetlen(arr, n);
  
  for (int i = 0; i < n; i++)
    arr[i] = js2vec2(js, JS_GetPropertyUint32(js, v, i));
    
  return arr;
}

static JSValue vecarr2js(JSContext *js, HMM_Vec2 *points, int n) {
  JSValue array = JS_NewArray(js);
  for (int i = 0; i < n; i++)
    JS_SetPropertyUint32(js, array, i, vec22js(js, points[i]));
    
  return array;
}

JSC_CCALL(spline_catmull,
  HMM_Vec2 *points = js2cpvec2arr(js, argv[0]);
  float param = js2number(js, argv[1]);
  HMM_Vec2 *samples = catmull_rom_ma_v2(points, param);

  if (!samples)
    ret = JS_NULL;
  else
    ret = vecarr2js(js, samples, arrlen(samples));

  arrfree(points);
  arrfree(samples);
)

JSC_CCALL(spline_bezier,
  HMM_Vec2 *points = js2cpvec2arr(js, argv[0]);
  float param = js2number(js, argv[1]);
  HMM_Vec2 *samples = bezier_cb_ma_v2(points, param);

  if (!samples)
    ret = JS_NULL;
  else
    ret = vecarr2js(js, samples, arrlen(samples));
    
  arrfree(samples);
  arrfree(points);  
)

static const JSCFunctionListEntry js_spline_funcs[] = {
  MIST_FUNC_DEF(spline, catmull, 2),
  MIST_FUNC_DEF(spline, bezier, 2)
};

JSValue js_spline_use(JSContext *js) {
  JSValue mod = JS_NewObject(js);
  JS_SetPropertyFunctionList(js, mod, js_spline_funcs, countof(js_spline_funcs));
  return mod;
}