#include "cell.h"
#include "cell_math.h"
#include <math.h>

static JSValue js_math_rad_arc_cosine (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, acos (x));
}

static JSValue js_math_rad_arc_sine (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, asin (x));
}

static JSValue js_math_rad_arc_tangent (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, atan (x));
}

static JSValue js_math_rad_cosine (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, cos (x));
}

static JSValue js_math_rad_sine (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, sin (x));
}

static JSValue js_math_rad_tangent (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
  double x;
  if (JS_ToFloat64 (ctx, &x, argv[0]) < 0) return JS_EXCEPTION;
  return JS_NewFloat64 (ctx, tan (x));
}

static const JSCFunctionListEntry js_math_radians_funcs[]
  = { JS_CFUNC_DEF ("arc_cosine", 1, js_math_rad_arc_cosine),
      JS_CFUNC_DEF ("arc_sine", 1, js_math_rad_arc_sine),
      JS_CFUNC_DEF ("arc_tangent", 1, js_math_rad_arc_tangent),
      JS_CFUNC_DEF ("cosine", 1, js_math_rad_cosine),
      JS_CFUNC_DEF ("sine", 1, js_math_rad_sine),
      JS_CFUNC_DEF ("tangent", 1, js_math_rad_tangent),
      JS_CFUNC_DEF ("ln", 1, js_math_ln),
      JS_CFUNC_DEF ("log", 1, js_math_log10),
      JS_CFUNC_DEF ("log2", 1, js_math_log2),
      JS_CFUNC_DEF ("power", 2, js_math_power),
      JS_CFUNC_DEF ("root", 2, js_math_root),
      JS_CFUNC_DEF ("sqrt", 1, js_math_sqrt),
      JS_CFUNC_DEF ("e", 1, js_math_e) };

JSValue js_core_math_radians_use (JSContext *ctx) {
  JSGCRef obj_ref;
  JS_PushGCRef (ctx, &obj_ref);
  obj_ref.val = JS_NewObject (ctx);
  JS_SetPropertyFunctionList (ctx, obj_ref.val, js_math_radians_funcs, countof (js_math_radians_funcs));
  JSValue result = obj_ref.val;
  JS_PopGCRef (ctx, &obj_ref);
  return result;
}
