#!/usr/bin/env bash
# build-sdl2.sh — Compile and run native-hello on macOS using the SDL2 backend.
#
# Usage:
#   ./build-sdl2.sh           # compile and run
#   ./build-sdl2.sh compile   # compile only
#   ./build-sdl2.sh clean     # remove build artefacts
#
# Requirements:
#   - elc in PATH (or ../../../lang/dist/platform/elc)
#   - SDL2, SDL2_ttf, SDL2_image via Homebrew (brew install sdl2 sdl2_ttf sdl2_image)
#   - clang (Xcode Command Line Tools)
#   - macOS 12+
#
# This is the SDL2 counterpart to build.sh (AppKit). The pipeline is identical;
# only the platform bridge object and compile flags differ:
#   - el_sdl2.c  instead of el_appkit.m
#   - -DEL_TARGET_SDL2 instead of -DEL_TARGET_MACOS
#   - sdl2-config --libs -lSDL2_ttf -lSDL2_image -ldl instead of -framework Cocoa

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang"
EL_UI_ROOT="${SCRIPT_DIR}/../.."
EL_RUNTIME="${EL_LANG_ROOT}/runtime"
EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el"
BUILD_DIR="${SCRIPT_DIR}/build"

# Locate elc
if command -v elc &>/dev/null; then
    ELC="elc"
elif [ -x "${EL_LANG_ROOT}/dist/platform/elc" ]; then
    ELC="${EL_LANG_ROOT}/dist/platform/elc"
else
    echo "Error: elc not found. Add it to PATH or place it at:"
    echo "  ${EL_LANG_ROOT}/dist/platform/elc"
    exit 1
fi

# Verify SDL2 is available
if ! command -v sdl2-config &>/dev/null; then
    echo "Error: sdl2-config not found. Install SDL2 via:"
    echo "  brew install sdl2 sdl2_ttf sdl2_image"
    exit 1
fi

SDL2_CFLAGS=$(sdl2-config --cflags)
SDL2_LIBS=$(sdl2-config --libs)

CLANG_FLAGS_COMMON=(
    -std=c11
    -DEL_TARGET_SDL2
    -I "${EL_RUNTIME}"
)

clean() {
    rm -rf "${BUILD_DIR}"
    echo "Cleaned."
}

compile() {
    mkdir -p "${BUILD_DIR}"

    # ── 1. Vessel forward-declarations header ─────────────────────────────────
    echo "==> Generating el-native vessel header (declarations only)..."
    "${ELC}" --emit-header "${EL_NATIVE_VESSEL}" \
        | awk 'BEGIN{in_body=0} /^[a-zA-Z_].+\)[[:space:]]*\{/ {in_body=1} !in_body{print}' \
        > "${BUILD_DIR}/el_native_vessel.h"

    # ── 2. Compile el-native vessel to C ──────────────────────────────────────
    echo "==> Compiling el-native vessel to C..."
    "${ELC}" "${EL_NATIVE_VESSEL}" \
        > "${BUILD_DIR}/el_native_vessel.c"

    # ── 3. Compile app entry to C ─────────────────────────────────────────────
    echo "==> Compiling app entry to C..."
    EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
        "${ELC}" "${SCRIPT_DIR}/src/main.el" \
        > "${BUILD_DIR}/native_hello.c"

    # ── 4. Compile el_sdl2.c (SDL2 bridge — pure C) ───────────────────────────
    # sdl2-config --cflags gives -I/opt/homebrew/include/SDL2 which handles
    # #include <SDL.h> but el_sdl2.c uses #include <SDL2/SDL.h> — also add
    # the parent directory so both forms resolve.
    echo "==> Compiling el_sdl2.c (SDL2 bridge)..."
    clang \
        -std=c11 \
        -DEL_TARGET_SDL2 \
        ${SDL2_CFLAGS} \
        -I/opt/homebrew/include \
        -I "${EL_RUNTIME}" \
        -c "${EL_RUNTIME}/el_sdl2.c" \
        -o "${BUILD_DIR}/el_sdl2.o"

    # ── 5a. Compile el_seed.c ─────────────────────────────────────────────────
    echo "==> Compiling el_seed.c..."
    clang "${CLANG_FLAGS_COMMON[@]}" \
        -c "${EL_RUNTIME}/el_seed.c" \
        -o "${BUILD_DIR}/el_seed.o"

    # ── 5b. Compile el_runtime.c and patch out duplicate __-prefixed symbols ──
    echo "==> Compiling el_runtime.c..."
    clang "${CLANG_FLAGS_COMMON[@]}" \
        -c "${EL_RUNTIME}/el_runtime.c" \
        -o "${BUILD_DIR}/el_runtime.o"

    echo "==> Patching el_runtime.o (hiding __-prefixed symbols duplicated in el_seed.o)..."
    nm "${BUILD_DIR}/el_seed.o" 2>/dev/null \
        | awk '/^[0-9a-f]+ T _/{print $3}' | sort > "${BUILD_DIR}/.seed_T.txt"
    nm "${BUILD_DIR}/el_runtime.o" 2>/dev/null \
        | awk '/^[0-9a-f]+ T _/{print $3}' | sort > "${BUILD_DIR}/.rt_T.txt"
    comm -23 "${BUILD_DIR}/.rt_T.txt" "${BUILD_DIR}/.seed_T.txt" \
        > "${BUILD_DIR}/.rt_keep.txt"
    nmedit -s "${BUILD_DIR}/.rt_keep.txt" "${BUILD_DIR}/el_runtime.o"

    # ── 6. Compile el-native vessel object ────────────────────────────────────
    echo "==> Compiling el-native vessel object..."
    clang "${CLANG_FLAGS_COMMON[@]}" \
        -include "${EL_RUNTIME}/el_native_target.h" \
        -c "${BUILD_DIR}/el_native_vessel.c" \
        -o "${BUILD_DIR}/el_native_vessel.o"

    echo "==> Patching el_native_vessel.o (hiding vessel main)..."
    nm "${BUILD_DIR}/el_native_vessel.o" 2>/dev/null \
        | awk '/^[0-9a-f]+ T _/{print $3}' \
        | grep -v '^_main$' \
        > "${BUILD_DIR}/.vessel_keep.txt"
    nmedit -s "${BUILD_DIR}/.vessel_keep.txt" "${BUILD_DIR}/el_native_vessel.o"

    # ── 7. Compile app object ─────────────────────────────────────────────────
    echo "==> Compiling app object..."
    clang "${CLANG_FLAGS_COMMON[@]}" \
        -include "${EL_RUNTIME}/el_native_target.h" \
        -include "${BUILD_DIR}/el_native_vessel.h" \
        -c "${BUILD_DIR}/native_hello.c" \
        -o "${BUILD_DIR}/native_hello.o"

    # ── 8. Link ───────────────────────────────────────────────────────────────
    echo "==> Linking native-hello-sdl2..."
    clang "${CLANG_FLAGS_COMMON[@]}" \
        ${SDL2_LIBS} \
        -lSDL2_ttf \
        -lSDL2_image \
        -lcurl \
        -ldl \
        -lpthread \
        "${BUILD_DIR}/native_hello.o" \
        "${BUILD_DIR}/el_native_vessel.o" \
        "${BUILD_DIR}/el_sdl2.o" \
        "${BUILD_DIR}/el_runtime.o" \
        "${BUILD_DIR}/el_seed.o" \
        -o "${BUILD_DIR}/native-hello-sdl2"

    echo "==> Build complete: ${BUILD_DIR}/native-hello-sdl2"
}

run() {
    compile
    echo "==> Launching native-hello-sdl2..."
    EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
        "${BUILD_DIR}/native-hello-sdl2"
}

case "${1:-run}" in
    clean)    clean   ;;
    compile)  compile ;;
    run|*)    run     ;;
esac
