#!/usr/bin/env bash
#
# Pre-commit guard: refuse to commit game data, disc images, or anything
# unusually large into this repository.
#
# This repository is a from-scratch Rust reimplementation. It contains NO
# game assets, NO disc images, NO BIOS dumps and NO proprietary SDK binaries.
# The build takes your own legally obtained copy of the disc as input.
#
# Hooks live in .githooks/ and are activated by `git config core.hooksPath`.
# To bypass in an emergency:  git commit --no-verify

set -uo pipefail

MAX_BYTES=$((50 * 1024 * 1024))   # 50 MiB

RED=$'\033[31m'; YEL=$'\033[33m'; RST=$'\033[0m'
errors=0

# Collect staged files (new/modified/renamed copies), NUL-separated so we
# survive spaces and odd characters in paths.
mapfile -d '' staged < <(
  git diff --cached --name-only --diff-filter=ACMR -z 2>/dev/null
)

if [ ${#staged[@]} -eq 0 ]; then
  exit 0
fi

for path in "${staged[@]}"; do
  # Blobs that were removed from the worktree still exist in the object DB.
  if ! [ -f "$path" ]; then
    size=$(git cat-file -s ":$path" 2>/dev/null || echo 0)
  else
    size=$(stat -c%s "$path" 2>/dev/null || echo 0)
  fi

  # 1) Disc-image / asset extensions.
  case "$path" in
    *.iso|*.bin|*.img|*.cue|*.mdf|*.rom|*.rom1|*.rom2)
      printf '%sBLOCKED%s  %s\n' "$RED" "$RST" "$path"
      printf '        looks like a disc image, BIOS dump or raw asset blob.\n'
      errors=1
      continue
      ;;
  esac

  # 2) Known extracted-asset directories.
  case "/$path/" in
    */extracted/*|*/assets/*|*/iso/*|*/disc/*)
      printf '%sBLOCKED%s  %s\n' "$RED" "$RST" "$path"
      printf '        lives in an asset directory that must stay untracked.\n'
      errors=1
      continue
      ;;
  esac

  # 3) Oversized files (catches archives and anything else we did not think of).
  if [ "$size" -gt "$MAX_BYTES" ]; then
    printf '%sBLOCKED%s  %s (%s MiB, limit 50)\n' \
      "$RED" "$RST" "$path" "$(( size / 1024 / 1024 ))"
    errors=1
    continue
  fi

  # 4) Content signature: ISO 9660 / WAD / CRI ADX container magic at offset 0.
  #    Catches disc images renamed to look like source. Compare the first five
  #    bytes as hex so binary bytes (NUL, 0x10, ...) cannot perturb the match.
  #    2048 bytes is one PS2 logical sector: the smallest plausible asset.
  if [ -f "$path" ] && [ "$size" -ge 2048 ]; then
    sig=$(head -c 5 "$path" 2>/dev/null | xxd -p | tr -d '\n')
    case "$sig" in
      4344303031*|574144*|414458*)
        printf '%sBLOCKED%s  %s\n' "$RED" "$RST" "$path"
        printf '        begins with a disc/asset container signature (%s).\n' "${sig:0:10}"
        errors=1
        continue
        ;;
    esac
  fi
done

if [ "$errors" -ne 0 ]; then
  cat <<EOF

${RED}Commit aborted.${RST} This repository must never contain game data.

  These files belong outside git (they are covered by .gitignore). Unstage them:
${YEL}    git reset${RST}
  and confirm with:
${YEL}    git status${RST}

  If something here is genuinely source code and larger than 50 MiB, that is
  itself worth investigating before committing it.

EOF
  exit 1
fi

exit 0