#!/usr/bin/env sh
# Compiles NTIA/itm (already fetched into vendor/) to WebAssembly via emcc.
# Expected to run inside the emscripten/emsdk Docker image (where `emcc`
# is on PATH), but will also work on a host with emscripten installed.
set -eu

HERE="$(cd "$(dirname "$0")" && pwd)"
cd "$HERE"

if [ ! -d vendor ]; then
  echo "[build] vendor/ missing — run fetch-vendor.sh first"
  exit 1
fi

# Output goes to dist/ inside this dir; the outer build step copies it to
# frontend/src/generated/itm/.
mkdir -p dist

# Exported C entry points. `_malloc` and `_free` are exposed so the TS
# wrapper can allocate the PFL array; `ITM_P2P_TLS_Ex` and `ITM_P2P_CR_Ex`
# give us both the loss and the intermediate diagnostic values.
EXPORTS='[
  "_ITM_P2P_TLS",
  "_ITM_P2P_TLS_Ex",
  "_ITM_P2P_CR",
  "_ITM_P2P_CR_Ex",
  "_ITM_AREA_TLS",
  "_ITM_AREA_TLS_Ex",
  "_ITM_AREA_CR",
  "_ITM_AREA_CR_Ex",
  "_malloc",
  "_free"
]'

RUNTIME_EXPORTS='[
  "HEAP8","HEAPU8","HEAP16","HEAPU16",
  "HEAP32","HEAPU32",
  "HEAPF32","HEAPF64",
  "getValue","setValue",
  "lengthBytesUTF8","stringToUTF8","UTF8ToString"
]'

# shellcheck disable=SC2046
emcc \
  -O3 \
  -std=c++17 \
  -DNDEBUG \
  -I vendor/include \
  -include "$HERE/shim.h" \
  $(find vendor/src -name '*.cpp' -print) \
  -s MODULARIZE=1 \
  -s EXPORT_ES6=1 \
  -s EXPORT_NAME=createItm \
  -s ENVIRONMENT='web,worker' \
  -s SINGLE_FILE=1 \
  -s ALLOW_MEMORY_GROWTH=1 \
  -s INITIAL_MEMORY=16MB \
  -s EXPORTED_FUNCTIONS="${EXPORTS}" \
  -s EXPORTED_RUNTIME_METHODS="${RUNTIME_EXPORTS}" \
  -s FILESYSTEM=0 \
  -s ASSERTIONS=0 \
  -o dist/itm.js

echo "[build] emitted dist/itm.js ($(wc -c < dist/itm.js) bytes)"

# The TS type shim isn't generated by emcc; we ship a hand-written one so
# consumer imports type-check cleanly.
cat > dist/itm.d.ts <<'EOF'
/**
 * Emscripten module produced by build.sh from NTIA/itm v1.4.
 * Auto-generated glue; hand-written `.d.ts` lives here so TS consumers
 * see a typed default export even when the .js is freshly rebuilt.
 */
export interface ItmModule {
  _malloc: (size: number) => number;
  _free: (ptr: number) => void;
  _ITM_P2P_TLS: (...args: number[]) => number;
  _ITM_P2P_TLS_Ex: (...args: number[]) => number;
  _ITM_P2P_CR: (...args: number[]) => number;
  _ITM_P2P_CR_Ex: (...args: number[]) => number;
  _ITM_AREA_TLS: (...args: number[]) => number;
  _ITM_AREA_TLS_Ex: (...args: number[]) => number;
  _ITM_AREA_CR: (...args: number[]) => number;
  _ITM_AREA_CR_Ex: (...args: number[]) => number;
  HEAP8: Int8Array;
  HEAPU8: Uint8Array;
  HEAP16: Int16Array;
  HEAPU16: Uint16Array;
  HEAP32: Int32Array;
  HEAPU32: Uint32Array;
  HEAPF32: Float32Array;
  HEAPF64: Float64Array;
  getValue(ptr: number, type: string): number;
  setValue(ptr: number, value: number, type: string): void;
}

declare const createItm: (overrides?: Partial<ItmModule>) => Promise<ItmModule>;
export default createItm;
EOF

echo "[build] wrote dist/itm.d.ts"
echo "[build] OK"
