// https://github.com/bytecodealliance/wasm-micro-runtime/blob/WAMR-2.4.4/doc/embed_wamr.md

// #include <stdio.h>
#include <string.h>

#include "lib.c"

// #include "bh_read_file.h"
#include "bh_platform.h"
#include "wasm_export.h"

#include "__WASM_ARRAY_FILE__"

#define STACK_SIZE (8 * 1024)
#define HEAP_SIZE (8 * 1024)

// TODO: Set this up so the lsp actually finds the includes...

MAIN() {
  char error_buf[128];
  wasm_module_t module;
  wasm_module_inst_t module_inst;
  wasm_function_inst_t func;
  wasm_exec_env_t exec_env;
  uint32 stack_size = 8 * 1024;
  uint32 heap_size = 8 * 1024;

  /* initialize the wasm runtime */
  RuntimeInitArgs init_args;
  memset(&init_args, 0, sizeof(init_args));

  init_args.mem_alloc_type = Alloc_With_System_Allocator;
  if (!wasm_runtime_full_init(&init_args)) {
    return;
  }

  /* parse the WASM file from buffer and create a WASM module */
  module = wasm_runtime_load(__WASM_ARRAY__, __WASM_ARRAY_LEN__, error_buf,
                             sizeof(error_buf));

  /* create an instance of the WASM module (WASM linear memory is ready) */
  module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
                                         error_buf, sizeof(error_buf));

  /* lookup a WASM function by its name, the function signature can NULL here */
  func = wasm_runtime_lookup_function(module_inst, "wasm_module");

  /* create an execution environment to execute arbitrary WASM functions */
  exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);

  /* arguments are always transferred in 32-bit element */
  uint32 args[1];

  /* call an arbitrary WASM function */
  MARKER(start_trace);
  if (!wasm_runtime_call_wasm(exec_env, func, 0, args)) {
    /* function wasn't called correctly */
    POSIX_PRINTF("Failed to call function 'wasm_module'!\n");
  }
  MARKER(stop_trace);

  POSIX_PRINTF("Sum: %d\n!", args[0]);

  /* the return value is stored in args[0] */
  if (args[0] == 100) {
    MARKER(ok_marker);
  } else {
    MARKER(fail_marker);
  }

  wasm_runtime_destroy_exec_env(exec_env);
  wasm_runtime_deinstantiate(module_inst);
  wasm_runtime_unload(module);
  wasm_runtime_destroy();
}
