#!/usr/bin/env bash
# tv-lib.sh – gemeinsame Funktionen für die Android-TV-Skripte (VisualAndroidTV)
#
# Wird von den anderen tv-*.sh-Skripten eingebunden, nicht direkt gestartet:
#   . "$(dirname "$0")/tv-lib.sh"
#
# Voraussetzungen:
#   - Android SDK Platform-Tools (adb) auf dem Rechner
#   - Entwickleroptionen + USB-/Netzwerk-Debugging auf dem EIGENEN Fernseher eingeschaltet
#   - Freigabedialog „USB-Debugging zulassen?“ am Fernseher einmal bestätigt
#
# Ziel wählen (Beispieladresse aus dem Dokumentationsnetz 192.0.2.0/24):
#   TV_HOST=192.0.2.50:5555 ./tv-info.sh
#   TV_HOST=tv.example.org:5555 ./tv-info.sh

TV_HOST="${TV_HOST:-192.0.2.50:5555}"   # Adresse:Port des Fernsehers (adbd lauscht auf TCP 5555)
ADB="${ADB:-adb}"                       # Pfad zum adb-Programm
TV_USER="${TV_USER:-0}"                 # Android-Benutzer; 0 = Hauptbenutzer

tv_die()  { printf 'Fehler: %s\n' "$*" >&2; exit 1; }
tv_info() { printf '%s\n' "$*" >&2; }

# Prüft, ob adb installiert ist.
tv_need_adb() {
  command -v "$ADB" >/dev/null 2>&1 \
    || tv_die "adb nicht gefunden – Android SDK Platform-Tools installieren."
}

# Zustand des Ziels laut „adb devices“: device | offline | unauthorized | (leer)
tv_state() {
  "$ADB" devices | tr -d '\r' | awk -v h="$TV_HOST" '$1 == h { print $2 }'
}

# Stellt die Verbindung her (falls nötig) und bricht mit klarer Meldung ab, wenn sie nicht steht.
tv_connect() {
  tv_need_adb
  local state
  state="$(tv_state)"
  if [ "$state" != "device" ]; then
    "$ADB" connect "$TV_HOST" >/dev/null 2>&1 || true
    state="$(tv_state)"
  fi
  case "$state" in
    device) return 0 ;;
    unauthorized)
      tv_die "$TV_HOST ist nicht freigegeben – Dialog „USB-Debugging zulassen?“ am Fernseher bestätigen." ;;
    offline)
      tv_die "$TV_HOST ist offline – Fernseher einschalten oder „adb disconnect“ und erneut versuchen." ;;
    *)
      tv_die "Keine Verbindung zu $TV_HOST – Adresse, Netzwerk und Debugging-Einstellung prüfen." ;;
  esac
}

# adb gezielt für diesen Fernseher aufrufen.
tv_adb() { "$ADB" -s "$TV_HOST" "$@"; }

# Shell-Befehl auf dem Fernseher; -n verhindert, dass adb die Standardeingabe des Skripts verbraucht.
tv_shell() { tv_adb shell -n "$@"; }

# Wie tv_shell, aber ohne Wagenrücklauf am Zeilenende (ältere Geräte liefern \r\n).
tv_out() { tv_shell "$@" | tr -d '\r'; }

# Text für die Shell AUF DEM FERNSEHER in einfache Anführungszeichen setzen.
tv_quote() {
  local s=$1
  s=${s//\'/\'\\\'\'}
  printf "'%s'" "$s"
}

# API-Level des Fernsehers (z. B. 33 für Android 13).
tv_sdk() { tv_out getprop ro.build.version.sdk; }

# Paketlisten einmal laden (spart viele einzelne adb-Aufrufe).
TV_PKG_INSTALLED=""
TV_PKG_DISABLED=""
TV_PKG_KNOWN=""
tv_load_packages() {
  TV_PKG_INSTALLED="$(tv_out pm list packages --user "$TV_USER")"
  TV_PKG_DISABLED="$(tv_out pm list packages -d --user "$TV_USER")"
  TV_PKG_KNOWN="$(tv_out pm list packages -u --user "$TV_USER")"
}

# Zustand eines Pakets: aktiv | deaktiviert | entfernt | fehlt
#   entfernt = für den Benutzer deinstalliert, liegt aber noch im System (wiederherstellbar)
#   fehlt    = auf diesem Gerät unbekannt
tv_pkg_state() {
  local line="package:$1"
  [ -n "$TV_PKG_KNOWN" ] || tv_load_packages
  if grep -qxF -- "$line" <<<"$TV_PKG_DISABLED"; then
    echo "deaktiviert"
  elif grep -qxF -- "$line" <<<"$TV_PKG_INSTALLED"; then
    echo "aktiv"
  elif grep -qxF -- "$line" <<<"$TV_PKG_KNOWN"; then
    echo "entfernt"
  else
    echo "fehlt"
  fi
}

# Paketnamen aus einer Liste lesen: eine Zeile je Paket, # leitet Kommentare ein.
tv_read_list() {
  [ -r "$1" ] || tv_die "Liste nicht lesbar: $1"
  sed -e 's/#.*$//' -e 's/^package://' -e 's/[[:space:]]//g' "$1" | grep -v '^$' || true
}

# Nur Zeichen zulassen, die in Paketnamen vorkommen.
tv_valid_package() {
  case "$1" in
    ""|*[!A-Za-z0-9._]*) return 1 ;;
    *.*) return 0 ;;
    android) return 0 ;;
    *) return 1 ;;
  esac
}
