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

ROOT="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
DEFAULT_INSTALLER='/mnt/smbgames/games/GOG/setup_quake_iv_1.4.3_lang_update_(63131).exe'
INSTALLER="${1:-${DEFAULT_INSTALLER}}"
DEST="${ROOT}/assets-src/gog/q4base"
FORCE=0

if [[ "${2:-}" == "--force" || "${1:-}" == "--force" ]]; then
  FORCE=1
  [[ "${1:-}" == "--force" ]] && INSTALLER="${DEFAULT_INSTALLER}"
fi

command -v innoextract >/dev/null || {
  echo "innoextract is required" >&2
  exit 1
}
[[ -f "${INSTALLER}" ]] || {
  echo "GOG installer not found: ${INSTALLER}" >&2
  exit 1
}
if [[ -e "${DEST}" && ${FORCE} -ne 1 ]]; then
  echo "Retail data already exists at ${DEST}; pass --force to replace it" >&2
  exit 2
fi

TMP="$(mktemp -d "${ROOT}/.tmp-retail.XXXXXX")"
STAGED=""
BACKUP=""
BACKUP_MANIFEST=""
MANIFEST="${ROOT}/runtime/retail-manifest.json"
COMMITTED=0
MANIFEST_INSTALLED=0
cleanup() {
  local status=$?
  set +e
  if [[ ${COMMITTED} -ne 1 ]]; then
    if [[ -n "${BACKUP}" && -e "${BACKUP}" ]]; then
      rm -rf -- "${DEST}"
      mv -- "${BACKUP}" "${DEST}"
    elif [[ -n "${STAGED}" && ! -e "${STAGED}" ]]; then
      rm -rf -- "${DEST}"
    fi
    if [[ -n "${BACKUP_MANIFEST}" && -e "${BACKUP_MANIFEST}" ]]; then
      rm -f -- "${MANIFEST}"
      mv -- "${BACKUP_MANIFEST}" "${MANIFEST}"
    elif [[ ${MANIFEST_INSTALLED} -eq 1 ]]; then
      rm -f -- "${MANIFEST}"
    fi
  fi
  [[ -z "${STAGED}" ]] || rm -rf -- "${STAGED}"
  rm -rf -- "${TMP}"
  trap - EXIT
  exit "${status}"
}
trap cleanup EXIT
innoextract --silent --extract --output-dir "${TMP}/extract" "${INSTALLER}"

mapfile -t BASES < <(find "${TMP}/extract" -type d -iname q4base -print)
[[ ${#BASES[@]} -eq 1 ]] || {
  printf 'Expected one q4base directory, found %d\n' "${#BASES[@]}" >&2
  exit 1
}
SOURCE="${BASES[0]}"

for index in $(seq -w 1 22); do
  [[ -s "${SOURCE}/pak0${index}.pk4" ]] || {
    echo "Installer is missing q4base/pak0${index}.pk4" >&2
    exit 1
  }
done
compgen -G "${SOURCE}/zpak_*.pk4" >/dev/null || {
  echo "Installer has no q4base/zpak_<language>.pk4" >&2
  exit 1
}

STAGED="${ROOT}/assets-src/gog/q4base.new.$$"
rm -rf -- "${STAGED}"
mkdir -p -- "${STAGED}"
rsync -a --include='*.pk4' --exclude='*' "${SOURCE}/" "${STAGED}/"
STAGED_MANIFEST="${TMP}/retail-manifest.json"
Q4_RETAIL_DIR="${STAGED}" Q4_RETAIL_MANIFEST="${STAGED_MANIFEST}" \
  node "${ROOT}/tools/stage-retail-manifest.mjs" --verify
if [[ -e "${DEST}" ]]; then
  BACKUP="${ROOT}/assets-src/gog/q4base.old.$$"
  mv -- "${DEST}" "${BACKUP}"
fi
mv -- "${STAGED}" "${DEST}"
mkdir -p -- "${ROOT}/runtime"
if [[ -e "${MANIFEST}" ]]; then
  BACKUP_MANIFEST="${MANIFEST}.old.$$"
  mv -- "${MANIFEST}" "${BACKUP_MANIFEST}"
fi
mv -- "${STAGED_MANIFEST}" "${MANIFEST}"
MANIFEST_INSTALLED=1
(
cd -- "${ROOT}"
Q4_RETAIL_DIR="${DEST}" Q4_RETAIL_MANIFEST="${MANIFEST}" node --input-type=module <<'NODE'
import { loadRetailCatalog } from './server/retail.js';
const catalog = loadRetailCatalog({
  enabled: true,
  directory: process.env.Q4_RETAIL_DIR,
  manifestFile: process.env.Q4_RETAIL_MANIFEST,
});
catalog.close();
NODE
)
COMMITTED=1
[[ -z "${BACKUP:-}" ]] || rm -rf -- "${BACKUP}"
[[ -z "${BACKUP_MANIFEST:-}" ]] || rm -f -- "${BACKUP_MANIFEST}"

printf 'Imported %s retail PK4 files (%s bytes) into %s\n' \
  "$(find "${DEST}" -maxdepth 1 -type f -iname '*.pk4' | wc -l)" \
  "$(du -sb "${DEST}" | awk '{print $1}')" \
  "${DEST}"
printf 'These files are ignored by Git; only the approved manifest catalog may expose them at runtime.\n'
