#!/usr/bin/env bash
# tmodc.sh — wrapper around modc.<version>
#
# Usage:
#   ./tmodc.sh [modc-options…] input.mc
#       Pass all arguments through to the Mod-c / TMod-c compiler.
#
#   ./tmodc.sh -run [modc-options…] input.mc [program-args…]
#       Generate C from input.mc, compile with cc (or $CC / $TMODC_CC),
#       run the binary with program-args (like tcc -run).
#
# Environment:
#   TMODC_BIN   Path to modc binary (default: <repo>/modc.0.25.1)
#   TMODC_CC    C compiler for -run (default: $CC, then cc)
#   TMODC_CFLAGS  Extra flags for -run link (appended after defaults)
#   TMODC_KEEP  If set non-empty, leave temp dir for -run (print path)
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="@INSTALL_DIR@"
DEFAULT_MODC="modc"
VERSION="@VERSION@"

# find executable
if [[ -n "${TMODC_BIN:-}" && -x "$TMODC_BIN" ]]; then
	MODC="$TMODC_BIN"
elif [[ -x "${SCRIPT_DIR}/modc" ]]; then
	MODC="${SCRIPT_DIR}/modc"
elif [[ -x "${SCRIPT_DIR}/modc.${VERSION}" ]]; then
	MODC="${SCRIPT_DIR}/modc.${VERSION}"
elif [[ -x "${INSTALL_DIR}/modc.${VERSION}" ]]; then
	MODC="${INSTALL_DIR}/modc.${VERSION}"
else
	MODC="${DEFAULT_MODC}"
fi

if [[ ! -x "$MODC" ]]; then
	echo "tmodc.sh: compiler not found or not executable: $MODC" >&2
	echo "  Build with: make   (or set TMODC_BIN)" >&2
	exit 127
fi

# --- pass-through mode (no -run) ---
if [[ "${1:-}" != "-run" ]]; then
	exec "$MODC" "$@"
fi

# --- -run mode ---
shift

if [[ $# -lt 1 ]]; then
	echo "Usage: $0 -run [modc-options…] input.mc [program-args…]" >&2
	exit 2
fi

modc_opts=()
mc_file=""
prog_args=()

# Options before the first *.mc go to modc; that file is the unit;
# everything after it is passed to the resulting program.
while [[ $# -gt 0 ]]; do
	case "$1" in
		*.mc)
			mc_file="$1"
			shift
			prog_args=("$@")
			break
			;;
		*)
			modc_opts+=("$1")
			shift
			;;
	esac
done

if [[ -z "$mc_file" ]]; then
	echo "tmodc.sh: -run requires an input .mc file" >&2
	exit 2
fi

if [[ ! -f "$mc_file" ]]; then
	echo "tmodc.sh: file not found: $mc_file" >&2
	exit 1
fi

# Resolve to absolute path so chdir does not break the unit path.
if command -v realpath >/dev/null 2>&1; then
	mc_abs="$(realpath "$mc_file")"
else
	mc_abs="$(cd "$(dirname "$mc_file")" && pwd)/$(basename "$mc_file")"
fi

stem="$(basename "$mc_file" .mc)"
tmp="$(mktemp -d "${TMPDIR:-/tmp}/tmodc.XXXXXX")"
cleanup() {
	if [[ -n "${TMODC_KEEP:-}" ]]; then
		echo "tmodc.sh: keeping $tmp" >&2
	else
		rm -rf "$tmp"
	fi
}
trap cleanup EXIT

c_file="${tmp}/${stem}.c"
h_file="${tmp}/${stem}.h"
bin_file="${tmp}/${stem}"

# Generate C (+ header so multi-file / #include patterns stay happy).
"$MODC" -q "$mc_abs" -C "$c_file" -H "$h_file" "${modc_opts[@]+"${modc_opts[@]}"}"

cc_cmd="${TMODC_CC:-${CC:-cc}}"
# Match Makefile test includes when building from the repo tree.
default_cflags=(
	"-std=c11"
	"-I${SCRIPT_DIR}/src"
	"-I${SCRIPT_DIR}/include"
	"-I${SCRIPT_DIR}/lib"
)
# shellcheck disable=SC2206
extra_cflags=( ${TMODC_CFLAGS:-} )

"$cc_cmd" "${default_cflags[@]}" "${extra_cflags[@]}" -o "$bin_file" "$c_file"

# Do not exec: EXIT trap must run to remove $tmp (unless TMODC_KEEP).
set +e
"$bin_file" "${prog_args[@]+"${prog_args[@]}"}"
status=$?
set -e
exit "$status"
