#include "lib.h"

#include "bh_platform.h"
#include "wasm_export.h"

#include "__WASM_ARRAY_FILE__"

#define STACK_SIZE (4 * 1024)
#define HEAP_SIZE STACK_SIZE
#define RUNTIME_POOL_SIZE 4 * STACK_SIZE

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;

  /* initialize the wasm runtime */
  static char global_heap_buf[RUNTIME_POOL_SIZE];
  static RuntimeInitArgs init_args;
  memset(&init_args, 0, sizeof(RuntimeInitArgs));

  init_args.mem_alloc_type = Alloc_With_Pool;
  init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
  init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
  init_args.max_thread_num = 1;
  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));

  if (!module) {
    return;
  }

  /* 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));

  if (!module_inst) {
    return;
  }

  /* 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_t args[1] = {0};

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

  uint32_t result = args[0];

  /* the return value is stored in args[0] */
  if (result == 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();

  return;
}
