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

build_root=$1
src=$2
python3_bin=$3
valac_bin=$4

runtime_pkg_args=(--pkg phpef-runtime-core --pkg phpef-runtime-embed)
if [ -n "${PHPEF_RUNTIME_NATIVE_PACKAGES:-}" ]; then
    old_ifs=$IFS; IFS=:
    for native_pkg in $PHPEF_RUNTIME_NATIVE_PACKAGES; do
        [ -n "$native_pkg" ] && runtime_pkg_args+=(--pkg "$native_pkg")
    done
    IFS=$old_ifs
elif [ -n "${PHPEF_RUNTIME_NATIVE_VAPIS:-}" ]; then
    old_ifs=$IFS; IFS=:
    for native_vapi in $PHPEF_RUNTIME_NATIVE_VAPIS; do
        [ -n "$native_vapi" ] || continue
        native_pkg=$(basename "$native_vapi" .vapi)
        runtime_pkg_args+=(--pkg "$native_pkg")
    done
    IFS=$old_ifs
fi

cli_dir="$build_root/src/cli"
php2ast="$cli_dir/phpefc-php2ast"
ast2php="$cli_dir/phpefc-ast2php"
phpast2phpir="$cli_dir/phpefc-phpast2phpir"
phpir2valair="$cli_dir/phpefc-phpir2valair"
valair2vala="$cli_dir/phpefc-valair2vala"
valair_optimize="$cli_dir/phpefc-valair-optimize-typing"

for tool in "$php2ast" "$ast2php" "$phpast2phpir" "$phpir2valair" "$valair_optimize" "$valair2vala"; do
    if [ ! -x "$tool" ]; then
        echo "missing built tool: $tool" >&2
        exit 99
    fi
done

work=${MESON_TEST_TMPDIR:-}
if [ -z "$work" ]; then
    work=$(mktemp -d)
    trap 'rm -rf "$work"' EXIT
fi
mkdir -p "$work"

phpast="$work/hallowelt.phpast"
orig_php="$work/hallowelt.orig.php"
phpir="$work/hallowelt.phpir"
valair="$work/hallowelt.valair"
vala="$work/hallowelt.vala"
bin="$work/hallowelt"
out="$work/hallowelt.out"
valac_extra_args=()
if [ -n "${PHPEF_RUNTIME_DEV_LIBDIR:-}" ]; then
    valac_extra_args+=("-X" "-Wl,-rpath,$PHPEF_RUNTIME_DEV_LIBDIR")
fi
if [ -n "${PHPEF_RUNTIME_VAPIDIR:-}" ]; then
    valac_extra_args+=("--vapidir=$PHPEF_RUNTIME_VAPIDIR")
else
    if [ -n "${PHPEF_RUNTIME_CORE_VAPI:-}" ]; then
        valac_extra_args+=("--vapidir=$(dirname "$PHPEF_RUNTIME_CORE_VAPI")")
    fi
    if [ -n "${PHPEF_RUNTIME_EMBED_VAPI:-}" ]; then
        valac_extra_args+=("--vapidir=$(dirname "$PHPEF_RUNTIME_EMBED_VAPI")")
    fi
    if [ -n "${PHPEF_RUNTIME_NATIVE_VAPIS:-}" ]; then
        old_ifs=$IFS; IFS=:
        for native_vapi in $PHPEF_RUNTIME_NATIVE_VAPIS; do
            [ -n "$native_vapi" ] || continue
            valac_extra_args+=("--vapidir=$(dirname "$native_vapi")")
        done
        IFS=$old_ifs
    fi
fi

"$php2ast" "$src" "$phpast"
"$ast2php" "$phpast" "$orig_php"

"$python3_bin" - "$src" "$orig_php" <<'PY'
import sys
from pathlib import Path

def without_final_linebreaks(path: str) -> bytes:
    return Path(path).read_bytes().rstrip(b"\r\n")

src, generated = sys.argv[1:]
if without_final_linebreaks(src) != without_final_linebreaks(generated):
    import difflib
    a = Path(src).read_text().splitlines(keepends=True)
    b = Path(generated).read_text().splitlines(keepends=True)
    sys.stderr.writelines(difflib.unified_diff(a, b, fromfile=src, tofile=generated))
    raise SystemExit("roundtrip mismatch: hallowelt.php != hallowelt.orig.php")
PY
printf 'ok 1 - hallowelt.php roundtrips to hallowelt.orig.php\n'

"$phpast2phpir" "$phpast" "$phpir"
"$phpir2valair" "$phpir" "$valair"
"$valair_optimize" "$valair" "$valair.afteropt.typing-zval2static"
"$valair2vala" "$valair.afteropt.typing-zval2static" "$vala"

if grep -Eq 'phpef_home_peters|home_peters_SVN' "$valair" "$vala"; then
    echo 'generated ValaIR/Vala leaked absolute host path into PHPEF symbol names' >&2
    grep -En 'phpef_home_peters|home_peters_SVN' "$valair" "$vala" >&2 || true
    exit 1
fi
if ! grep -Fq 'phpef_file_hallowelt_php' "$valair" || ! grep -Fq 'phpef_file_hallowelt_php' "$vala"; then
    echo 'generated ValaIR/Vala does not use the relative source prefix hallowelt_php' >&2
    cat "$vala" >&2
    exit 1
fi
printf 'ok 2 - generated ValaIR/Vala symbols use relative source names\n'

"$valac_bin" "${valac_extra_args[@]}" "${runtime_pkg_args[@]}" "$vala" -o "$bin"
"$bin" > "$out"

expected='Hallo Welt1ab!'
actual=$(cat "$out")
if [ "$actual" != "$expected" ]; then
    printf 'unexpected output\nexpected: %s\nactual:   %s\n' "$expected" "$actual" >&2
    exit 1
fi
printf 'ok 3 - generated binary output matches expected text\n'
