/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#include "scripter.h"

void scripterInit(scripter_t *scripter, engine_t *engine) {
  scripter->context = duk_create_heap_default();
  scripter->engine = engine;
  
  // Global context is implied here?
  // Push the script self reference
  duk_push_pointer(scripter->context, scripter);
  duk_put_global_string(scripter->context, SCRIPTER_SELF_NAME);
}

void scripterDispose(scripter_t *scripter) {
  duk_destroy_heap(scripter->context);
}

scripter_t * scripterFromContext(scriptercontext_t *ctx) {
  // Switch to global object
  duk_push_global_object(ctx);

  // Get the string in the object.
  duk_get_prop_string(ctx, -1, SCRIPTER_SELF_NAME);

  // Get the pointer from that string.
  scripter_t *scripter = (scripter_t *)duk_get_pointer(ctx, -1);

  // Pop the string.
  duk_pop(ctx);

  // Pop the global.
  duk_pop(ctx);
  
  return scripter;
}

void scripterDefineMethod(scripter_t *scripter,
  char *name, int32_t argCount, scriptermethod_t *method
) {
	duk_push_c_function(scripter->context, method, argCount);
	duk_put_global_string(scripter->context, name);
}

bool scripterInvokeMethodSimple(scripter_t *scripter, char *method) {
  // Push global
  duk_push_global_object(scripter->context);

  // Push method string
  duk_get_prop_string(scripter->context, -1, method);

  // Invoke string method
  if(duk_pcall(scripter->context, 0) != 0) {
    printf("Error: %s\n", duk_safe_to_string(scripter->context, -1));
    return false;
  }

  // Pop result
  duk_pop(scripter->context);

  // Pop global
  duk_pop(scripter->context);

  return true;
}