#!/usr/bin/env bash
# docker-build-linux.sh — Build native-hello for Linux using Docker.
#
# Usage:
#   ./docker-build-linux.sh              # build ARM64 (native on Apple Silicon)
#   ./docker-build-linux.sh --x86        # also build x86_64 via QEMU
#   ./docker-build-linux.sh --x86-only   # only build x86_64
#
# Output binaries are placed in ./build/:
#   native-hello-linux-arm64    — Linux ARM64 (Raspberry Pi 3/4/5, Apple Silicon VMs)
#   native-hello-linux-x86_64  — Linux x86_64 (desktop Linux, CI servers)
#
# Prerequisites:
#   - Docker (Rancher Desktop / Docker Desktop)
#   - elc at ../../../lang/dist/platform/elc or in PATH
#
# How it works:
#   1. elc generates C sources from the el program (macOS, ARM64 native elc)
#   2. Docker builds those C sources inside Ubuntu 22.04 + GTK4
#   3. The resulting ELF binary is extracted from the image
#
# Linux toolchain notes:
#   - GNU ld rejects duplicate symbol definitions that macOS ld accepts silently.
#     The Dockerfile uses objcopy --localize-symbol to hide duplicates between
#     el_seed.o / el_runtime.o and el_native_vessel.o / native_hello.o.
#   - el_gtk4.c requires _GNU_SOURCE for RTLD_DEFAULT (dlfcn.h).
#   - G_APPLICATION_DEFAULT_FLAGS was added in GLib 2.74; Ubuntu 22.04 ships
#     GLib 2.72, so the Dockerfile adds a compatibility define.

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"
DOCKER_CTX="${SCRIPT_DIR}/build-docker"

BUILD_X86=0
BUILD_ARM64=1

for arg in "$@"; do
    case "${arg}" in
        --x86)      BUILD_X86=1 ;;
        --x86-only) BUILD_X86=1; BUILD_ARM64=0 ;;
    esac
done

# ── 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 at:"
    echo "  ${EL_LANG_ROOT}/dist/platform/elc"
    exit 1
fi

# ── Step 1: Generate C sources ────────────────────────────────────────────────
echo "==> Generating C sources with elc..."
mkdir -p "${DOCKER_CTX}/runtime"

# App
EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
    "${ELC}" "${SCRIPT_DIR}/src/main.el" > "${DOCKER_CTX}/native_hello.c"

# Vessel
"${ELC}" "${EL_NATIVE_VESSEL}" > "${DOCKER_CTX}/el_native_vessel.c"

# Vessel header (declarations only — stop before first function body)
"${ELC}" --emit-header "${EL_NATIVE_VESSEL}" \
    | awk 'BEGIN{in_body=0} /^[a-zA-Z_].+\)[[:space:]]*\{/ {in_body=1} !in_body{print}' \
    > "${DOCKER_CTX}/el_native_vessel.h"

# Runtime C sources
cp "${EL_RUNTIME}/el_gtk4.c" \
   "${EL_RUNTIME}/el_seed.c" \
   "${EL_RUNTIME}/el_seed.h" \
   "${EL_RUNTIME}/el_runtime.c" \
   "${EL_RUNTIME}/el_runtime.h" \
   "${EL_RUNTIME}/el_native_target.h" \
   "${DOCKER_CTX}/runtime/"

echo "==> C sources ready in ${DOCKER_CTX}/"

mkdir -p "${BUILD_DIR}"

# ── Step 2: Docker build (ARM64) ─────────────────────────────────────────────
if [ "${BUILD_ARM64}" -eq 1 ]; then
    echo "==> Building Linux ARM64 image..."
    docker build \
        --platform linux/arm64 \
        -f "${SCRIPT_DIR}/Dockerfile.linux-gtk4" \
        --tag el-native-linux-gtk4-arm64 \
        "${DOCKER_CTX}/"

    echo "==> Extracting ARM64 binary..."
    docker create --name el-extract-arm64 el-native-linux-gtk4-arm64
    docker cp el-extract-arm64:/build/native-hello-linux "${BUILD_DIR}/native-hello-linux-arm64"
    docker rm el-extract-arm64

    echo "==> ARM64 binary: ${BUILD_DIR}/native-hello-linux-arm64"
    file "${BUILD_DIR}/native-hello-linux-arm64"
fi

# ── Step 3: Docker build (x86_64) ────────────────────────────────────────────
if [ "${BUILD_X86}" -eq 1 ]; then
    echo "==> Building Linux x86_64 image (QEMU emulation — slower)..."
    docker build \
        --platform linux/amd64 \
        -f "${SCRIPT_DIR}/Dockerfile.linux-gtk4" \
        --tag el-native-linux-gtk4-x86_64 \
        "${DOCKER_CTX}/"

    echo "==> Extracting x86_64 binary..."
    docker create --name el-extract-x86 el-native-linux-gtk4-x86_64
    docker cp el-extract-x86:/build/native-hello-linux "${BUILD_DIR}/native-hello-linux-x86_64"
    docker rm el-extract-x86

    echo "==> x86_64 binary: ${BUILD_DIR}/native-hello-linux-x86_64"
    file "${BUILD_DIR}/native-hello-linux-x86_64"
fi

echo ""
echo "==> Done. Binaries in ${BUILD_DIR}/"
ls -lh "${BUILD_DIR}"/native-hello-linux-* 2>/dev/null || true
