#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
VENDOR_DIR="$ROOT_DIR/vendor/linuxcnc"
WRAP_DIR="$ROOT_DIR/runtime/core/linuxcnc_wrap"
SHIM_DIR="$ROOT_DIR/runtime/core/shims"
INCLUDE_DIR="$ROOT_DIR/runtime/core/include"
OUT_DIR="$ROOT_DIR/build/wasm/core"
BUILD_DIR="$OUT_DIR"
OBJ_DIR="$BUILD_DIR/obj"

source "$ROOT_DIR/tools/wasm_incremental_build_lib.sh"

mkdir -p "$OUT_DIR" "$OBJ_DIR"

TARGET="linuxcnc_interp_wasm"
: > "$BUILD_DIR/$TARGET.stdout.log"
: > "$BUILD_DIR/$TARGET.stderr.log"

COMMON_FLAGS=(
  -std=c++20
  -O2
  -D_GNU_SOURCE
  -DM_PI=3.14159265358979323846
  -DOBJECT_FWD_DWA2002724_HPP
  -DUNIT_TEST
  -DLINUXCNC_STANDALONE_USE_RS274_PRE_STATE
  -DEMC2_HOME=\"/standalone\"
  -include "$SHIM_DIR/linuxcnc_wasm_compat.hh"
  -I"$WRAP_DIR"
  -I"$SHIM_DIR"
  -I"$INCLUDE_DIR"
  -I"$VENDOR_DIR/src"
  -I"$VENDOR_DIR/src/rtapi"
  -I"$VENDOR_DIR/src/emc"
  -I"$VENDOR_DIR/src/emc/nml_intf"
  -I"$VENDOR_DIR/src/emc/motion"
  -I"$VENDOR_DIR/src/emc/tp"
  -I"$VENDOR_DIR/src/emc/kinematics"
  -I"$VENDOR_DIR/src/emc/ini"
  -I"$VENDOR_DIR/src/libnml/posemath"
)

INTERP_CORE_SOURCES=(
  "$VENDOR_DIR/src/emc/rs274ngc/modal_state.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_array.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_internal.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_read.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_check.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_arc.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_inverse.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_execute.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_convert.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_cycles.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_g7x.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_queue.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_find.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_namedparams.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_write.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_o_word.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/interp_remap.cc"
  "$VENDOR_DIR/src/emc/rs274ngc/rs274ngc_pre.cc"
  "$VENDOR_DIR/src/emc/tooldata/tooldata_common.cc"
  "$WRAP_DIR/linuxcnc_hal_adapter.cpp"
  "$WRAP_DIR/linuxcnc_emc_status_runtime.cpp"
  "$WRAP_DIR/linuxcnc_interp_python_edge_stubs.cpp"
  "$WRAP_DIR/linuxcnc_machine_config.cpp"
  "$WRAP_DIR/linuxcnc_runtime_state_stubs.cpp"
  "$WRAP_DIR/linuxcnc_tool_adapter.cpp"
  "$WRAP_DIR/linuxcnc_interp_minimal_runtime.cpp"
  "$WRAP_DIR/linuxcnc_wasm_posix_stubs.cpp"
  "$VENDOR_DIR/src/emc/ini/inifile.cc"
)

SOURCES=(
  "${INTERP_CORE_SOURCES[@]}" \
  "$WRAP_DIR/linuxcnc_interp_wasm.cpp" \
)

OBJECTS=()
for source in "${SOURCES[@]}"; do
  obj="$(source_object_path "$source" "$ROOT_DIR" "$OBJ_DIR")"
  OBJECTS+=("$obj")
  compile_wasm_object "$TARGET" "$source" "$obj" "$BUILD_DIR" "${COMMON_FLAGS[@]}"
done

link_wasm_module \
  "$TARGET" \
  "$OUT_DIR/linuxcnc_interp.js" \
  "$BUILD_DIR" \
  -O2 \
  "${OBJECTS[@]}" \
  -s MODULARIZE=1 \
  -s EXPORT_ES6=1 \
  -s ENVIRONMENT=web,node \
  -s ALLOW_MEMORY_GROWTH=1 \
  -s STACK_SIZE=2MB \
  -s NO_EXIT_RUNTIME=1 \
  -s FORCE_FILESYSTEM=1 \
  -s EXPORTED_FUNCTIONS='["_malloc","_free","_lcinterp_run_program","_lcinterp_run_program_with_ini","_lcinterp_run_file","_lcinterp_run_file_with_ini","_lcinterp_run_file_with_ini_continue_on_error","_lcinterp_run_fiveaxis_remap_file","_lcinterp_run_remap_file","_lcinterp_run_remap_file_continue_on_error","_lcinterp_run_remap_io_mdi_sequence","_lcinterp_restore_parameters","_lcinterp_save_parameters","_lcinterp_load_tool_table","_lcinterp_load_tool_table_random","_lcinterp_save_tool_table","_lcinterp_probe_init_and_synch","_lcinterp_probe_indexer","_lcinterp_probe_named_parameters","_lcinterp_free_string"]' \
  -s EXPORTED_RUNTIME_METHODS='["FS","UTF8ToString","stringToUTF8","lengthBytesUTF8"]'
