#!/usr/bin/env bash
# Stitch our W65816 backend into the ephemeral llvm-mos checkout.
#
# Two-step process:
#   1. For every file under src/, create a symlink at the matching path
#      inside tools/llvm-mos/.  That way editing a file under src/ is
#      immediately reflected in the build tree.
#   2. Apply every patch under patches/ with `git apply`.  Patches that
#      are already applied (git detects this) are skipped silently.
#
# Safe to re-run.

set -euo pipefail
source "$(dirname "$0")/common.sh"

LLVM_SRC="$TOOLS_DIR/llvm-mos"
SRC_TREE="$PROJECT_ROOT/src"
PATCH_DIR="$PROJECT_ROOT/patches"

[ -d "$LLVM_SRC/.git" ] || die "llvm-mos checkout not found at $LLVM_SRC; run setup.sh first"
[ -d "$SRC_TREE" ] || die "src/ tree missing"

# 1. Symlinks.  For each file in src/<rel> we want a symlink at
# $LLVM_SRC/<rel>.  Relative target path keeps the clone portable if
# someone moves it, though our setup.sh always uses an absolute path.
log "linking src/ files into $LLVM_SRC"
linkedCount=0
skippedCount=0
while IFS= read -r -d '' file; do
    rel="${file#$SRC_TREE/}"
    dest="$LLVM_SRC/$rel"
    destDir="$(dirname "$dest")"
    install -d "$destDir"

    if [ -L "$dest" ]; then
        currentTarget="$(readlink "$dest")"
        if [ "$currentTarget" = "$file" ]; then
            skippedCount=$((skippedCount + 1))
            continue
        fi
        warn "replacing stale symlink: $rel"
        rm "$dest"
    elif [ -e "$dest" ]; then
        die "refusing to overwrite non-symlink file: $dest"
    fi

    ln -s "$file" "$dest"
    linkedCount=$((linkedCount + 1))
done < <(find "$SRC_TREE" -type f -print0)

log "symlinks: $linkedCount created, $skippedCount already current"

# 2. Patches.  git apply is idempotent via --reverse-check: if a patch
# is already applied, `git apply --reverse --check` succeeds and we skip.
log "applying patches from $PATCH_DIR"
appliedCount=0
reappliedCount=0
for patch in "$PATCH_DIR"/*.patch; do
    [ -f "$patch" ] || continue
    name="$(basename "$patch")"

    if git -C "$LLVM_SRC" apply --reverse --check "$patch" >/dev/null 2>&1; then
        reappliedCount=$((reappliedCount + 1))
        continue
    fi

    if ! git -C "$LLVM_SRC" apply --check "$patch" >/dev/null 2>&1; then
        die "patch fails to apply cleanly: $name. The llvm-mos tree may have drifted; run scripts/updateLlvmMos.sh."
    fi

    git -C "$LLVM_SRC" apply "$patch"
    log "  applied: $name"
    appliedCount=$((appliedCount + 1))
done

log "patches: $appliedCount newly applied, $reappliedCount already present"
log "backend stitched in at $LLVM_SRC"
