#!/usr/bin/env bash
# Strip the hardcoded external asset references from an installed gradio
# frontend, so a browser on an isolated network never waits on them.
#
#   scripts/patch-offline-assets.sh <venv>            # apply
#   scripts/patch-offline-assets.sh <venv> --restore  # undo
#   scripts/patch-offline-assets.sh <venv> --check    # report only
#
# Affects gradio 4.x only. gradio 6's frontend references no external hosts, so
# the script reports nothing to do there.
#
# gradio 4's templates/frontend/index.html hardcodes:
#   * a preconnect to fonts.googleapis.com and fonts.gstatic.com  (hints)
#   * a <script src=cdnjs.cloudflare.com ...iframeResizer...>     (real fetch)
# The iframe resizer only matters when the app is embedded in an iframe on a
# hosted page; nothing in a self-hosted deployment needs it.
#
# Google Fonts *stylesheets* come from the theme, not this file, and are not
# patched here. Remove them by choosing local font families:
#
#   theme = gr.themes.Default(font=["system-ui", "sans-serif"],
#                             font_mono=["ui-monospace", "monospace"])
#   with gr.Blocks(theme=theme) as demo: ...
#
# Originals are kept as <file>.orig, so --restore is always possible. Rerunning
# pip install on gradio replaces these files and the patch must be reapplied.
set -euo pipefail

usage() { sed -n '2,12p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 1; }
[[ $# -ge 1 ]] || usage
VENV="$1"; MODE="${2:---apply}"

[[ -x "$VENV/bin/python" ]] || { echo "ERROR: not a venv: $VENV" >&2; exit 1; }

GRADIO_DIR="$("$VENV/bin/python" -c 'import os,gradio;print(os.path.dirname(gradio.__file__))')"
GRADIO_VER="$("$VENV/bin/python" -c 'import gradio;print(gradio.__version__)')"
echo "==> gradio $GRADIO_VER in $GRADIO_DIR"

mapfile -t FILES < <(find "$GRADIO_DIR/templates" -name '*.html' 2>/dev/null || true)
[[ ${#FILES[@]} -gt 0 ]] || { echo "no template HTML found; nothing to do"; exit 0; }

PATTERN='fonts\.googleapis\.com|fonts\.gstatic\.com|cdnjs\.cloudflare\.com'
changed=0

for f in "${FILES[@]}"; do
  case "$MODE" in
    --check)
      if grep -qE "$PATTERN" "$f"; then
        echo "    external refs in $(basename "$f"):"
        grep -oE "https://($PATTERN)[^\"' ]*" "$f" | sort -u | sed 's/^/      /'
        changed=1
      fi
      ;;
    --restore)
      if [[ -f "$f.orig" ]]; then
        mv -f "$f.orig" "$f"
        echo "    restored $(basename "$f")"
        changed=1
      fi
      ;;
    --apply)
      grep -qE "$PATTERN" "$f" || continue
      [[ -f "$f.orig" ]] || cp -p "$f" "$f.orig"
      # Delete the two preconnect <link> elements and the cdnjs <script>
      # element. Each spans several lines, so match from the opening tag to
      # its terminator rather than line by line.
      "$VENV/bin/python" - "$f" <<'PY'
import re, sys
path = sys.argv[1]
with open(path, encoding="utf-8") as fh:
    html = fh.read()
before = html
# <link ... fonts.googleapis.com|fonts.gstatic.com ... />
html = re.sub(r'[ \t]*<link\b[^>]*?(?:fonts\.googleapis\.com|fonts\.gstatic\.com)[^>]*?/?>\n?',
              '', html, flags=re.S)
# <script ... cdnjs.cloudflare.com ... ></script>
html = re.sub(r'[ \t]*<script\b[^>]*?cdnjs\.cloudflare\.com.*?</script>\n?',
              '', html, flags=re.S)
if html != before:
    with open(path, "w", encoding="utf-8") as fh:
        fh.write(html)
    print("    patched %s" % path.split("/")[-1])
PY
      changed=1
      ;;
    *) usage ;;
  esac
done

if [[ "$MODE" == --apply ]]; then
  echo "==> verifying"
  left=0
  for f in "${FILES[@]}"; do
    if grep -qE "$PATTERN" "$f"; then
      echo "    STILL PRESENT in $(basename "$f")"; left=1
    fi
  done
  [[ $left == 0 ]] && echo "    no external asset references remain in the templates"
fi

[[ $changed == 0 ]] && echo "    nothing to do"
exit 0
