#!/usr/bin/env bash
# Prayer Times mosque screen for Raspberry Pi (and other Debian-based mini PCs).
#
# Turns the device into a screen that boots straight into the mosque display,
# full screen, with nothing else on it. It survives power cuts, never blanks,
# restarts the browser if it ever stops, and keeps its browser profile so the
# display's three months of saved times work without Wi-Fi.
#
#   curl -fsSL https://prayer.yazanmy.com/pi/install.sh | sudo bash -s -- "https://prayer.yazanmy.com/mosque?id=abc2345"
#
# Options (after the URL):
#   --rotate 90|180|270   turn the picture (portrait screens)
#   --uninstall           remove everything this script added
#
# Raspberry Pi OS Lite: runs the browser in the "cage" kiosk compositor as a
# system service on the first screen. Raspberry Pi OS with desktop: starts it
# full screen when the desktop logs in.
set -euo pipefail

URL=""
ROTATE=""
UNINSTALL=0
while [ $# -gt 0 ]; do
  case "$1" in
    --rotate) ROTATE="${2:-}"; shift 2 ;;
    --uninstall) UNINSTALL=1; shift ;;
    -h|--help) sed -n '2,17p' "$0" 2>/dev/null || true; exit 0 ;;
    *) URL="$1"; shift ;;
  esac
done

say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
die() { printf '\033[1;31mError:\033[0m %s\n' "$*" >&2; exit 1; }

[ "$(id -u)" -eq 0 ] || die "run with sudo (see the command at the top of this script)."
command -v apt-get >/dev/null || die "this needs Raspberry Pi OS or another Debian-based system."

KIOSK_USER="prayerscreen"
LAUNCHER="/usr/local/bin/prayer-display-browser"
SERVICE="/etc/systemd/system/prayer-display.service"
TIMER="/etc/systemd/system/prayer-display-restart.timer"
RESTART_UNIT="/etc/systemd/system/prayer-display-restart.service"
CONF="/etc/prayer-display.conf"
HAS_SYSTEMD=0
[ -d /run/systemd/system ] && HAS_SYSTEMD=1

if [ "$UNINSTALL" -eq 1 ]; then
  say "Removing the mosque screen"
  if [ "$HAS_SYSTEMD" -eq 1 ]; then
    systemctl disable --now prayer-display.service prayer-display-restart.timer 2>/dev/null || true
    systemctl enable getty@tty1.service 2>/dev/null || true
  fi
  rm -f "$SERVICE" "$TIMER" "$RESTART_UNIT" "$LAUNCHER" "$CONF"
  for home in /home/*; do rm -f "$home/.config/autostart/prayer-display.desktop"; done
  [ "$HAS_SYSTEMD" -eq 1 ] && systemctl daemon-reload
  say "Done. The '$KIOSK_USER' user and installed packages were left in place."
  exit 0
fi

case "$URL" in
  https://*|http://*) ;;
  "") die "give the display link, e.g. https://prayer.yazanmy.com/mosque?id=abc2345 (Tools → Mosque display → Copy link)." ;;
  *) die "the link must start with https://" ;;
esac
case "$ROTATE" in ""|90|180|270) ;; *) die "--rotate takes 90, 180 or 270" ;; esac

# Desktop if a graphical session is installed and set as the boot target.
DESKTOP=0
if [ "$HAS_SYSTEMD" -eq 1 ] && systemctl get-default 2>/dev/null | grep -q graphical && { [ -e /usr/bin/labwc ] || [ -e /usr/bin/wayfire ] || [ -e /usr/bin/startlxde-pi ] || [ -e /usr/bin/lxsession ]; }; then
  DESKTOP=1
fi

say "Installing the browser"
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
# Raspberry Pi OS calls it chromium-browser, Debian chromium.
candidate() { apt-cache policy "$1" 2>/dev/null | awk '/Candidate:/ {print $2}'; }
if [ -n "$(candidate chromium-browser)" ] && [ "$(candidate chromium-browser)" != "(none)" ] && ! apt-cache show chromium-browser 2>/dev/null | grep -q "transitional"; then BROWSER_PKG=chromium-browser; else BROWSER_PKG=chromium; fi
PKGS="$BROWSER_PKG"
[ "$DESKTOP" -eq 0 ] && PKGS="$PKGS cage wlr-randr"
# shellcheck disable=SC2086
apt-get install -y -qq --no-install-recommends $PKGS fonts-noto-core >/dev/null
BROWSER_BIN="$(command -v chromium-browser || command -v chromium)" || die "the browser did not install."

printf 'URL=%q\nROTATE=%q\n' "$URL" "$ROTATE" > "$CONF"

say "Writing the launcher"
cat > "$LAUNCHER" <<EOF
#!/usr/bin/env bash
# Starts the mosque display full screen. Generated by prayer-times install.sh.
. $CONF
PROFILE="\$HOME/.config/prayer-display"
mkdir -p "\$PROFILE/Default"
# After a power cut Chromium thinks it crashed and offers to restore: tell it the last exit was clean.
if [ -f "\$PROFILE/Default/Preferences" ]; then
  sed -i 's/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[A-Za-z]*"/"exit_type":"Normal"/' "\$PROFILE/Default/Preferences"
fi
if [ -n "\$ROTATE" ] && command -v wlr-randr >/dev/null && [ -n "\${WAYLAND_DISPLAY:-}" ]; then
  OUT="\$(wlr-randr | awk 'NR==1{print \$1}')"
  [ -n "\$OUT" ] && wlr-randr --output "\$OUT" --transform "\$ROTATE" || true
fi
exec $BROWSER_BIN \\
  --user-data-dir="\$PROFILE" \\
  --kiosk --start-fullscreen \\
  --noerrdialogs --disable-infobars --disable-session-crashed-bubble \\
  --disable-features=Translate,TranslateUI,MediaRouter \\
  --check-for-update-interval=31536000 \\
  --autoplay-policy=no-user-gesture-required \\
  --password-store=basic \\
  --ozone-platform-hint=auto \\
  "\$URL"
EOF
chmod 755 "$LAUNCHER"

if [ "$DESKTOP" -eq 1 ]; then
  # Raspberry Pi OS with desktop: open on login, keep the screen awake.
  TARGET_USER="${SUDO_USER:-$(logname 2>/dev/null || echo pi)}"
  TARGET_HOME="$(getent passwd "$TARGET_USER" | cut -d: -f6)"
  [ -n "$TARGET_HOME" ] || die "could not find the desktop user's home folder."
  say "Starting the display when $TARGET_USER's desktop opens"
  install -d -o "$TARGET_USER" -g "$TARGET_USER" "$TARGET_HOME/.config/autostart"
  cat > "$TARGET_HOME/.config/autostart/prayer-display.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=Prayer Times display
Exec=$LAUNCHER
X-GNOME-Autostart-enabled=true
EOF
  chown "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.config/autostart/prayer-display.desktop"
  command -v raspi-config >/dev/null && raspi-config nonint do_blanking 1 || true
  # Desktop autologin, so a power cut comes back to the display without a password prompt.
  command -v raspi-config >/dev/null && raspi-config nonint do_boot_behaviour B4 || true
else
  # Lite: a dedicated user runs the browser in cage on the first screen.
  say "Setting up the kiosk user and service"
  id "$KIOSK_USER" >/dev/null 2>&1 || useradd --create-home --shell /usr/sbin/nologin "$KIOSK_USER"
  for g in video render input audio; do getent group "$g" >/dev/null && usermod -aG "$g" "$KIOSK_USER"; done
  cat > "$SERVICE" <<EOF
[Unit]
Description=Prayer Times mosque display
After=systemd-user-sessions.service plymouth-quit-wait.service getty@tty1.service
Wants=network-online.target
Conflicts=getty@tty1.service

[Service]
User=$KIOSK_USER
PAMName=login
TTYPath=/dev/tty1
StandardInput=tty
StandardOutput=journal
StandardError=journal
UtmpIdentifier=tty1
UtmpMode=user
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
Environment=XDG_SESSION_TYPE=wayland
ExecStart=/usr/bin/cage -s -- $LAUNCHER
# Power cut, crash or hang: come back on its own.
Restart=always
RestartSec=5

[Install]
WantedBy=graphical.target
EOF
  # A fresh browser once a day, mid-morning: well after Fajr and sunrise, before Dhuhr, never during Taraweeh or Tahajjud.
  cat > "$RESTART_UNIT" <<EOF
[Unit]
Description=Daily fresh start of the Prayer Times display

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart prayer-display.service
EOF
  cat > "$TIMER" <<EOF
[Unit]
Description=Daily fresh start of the Prayer Times display

[Timer]
OnCalendar=*-*-* 10:15:00
Persistent=false

[Install]
WantedBy=timers.target
EOF
  # Keep the console from blanking the screen.
  for f in /boot/firmware/cmdline.txt /boot/cmdline.txt; do
    if [ -f "$f" ] && ! grep -q "consoleblank=0" "$f"; then sed -i '1 s/$/ consoleblank=0/' "$f"; break; fi
  done
  if [ "$HAS_SYSTEMD" -eq 1 ]; then
    systemctl daemon-reload
    systemctl set-default graphical.target >/dev/null
    systemctl disable getty@tty1.service >/dev/null 2>&1 || true
    systemctl enable prayer-display.service prayer-display-restart.timer >/dev/null
  else
    say "No systemd here (a container?): files written, nothing enabled."
  fi
fi

say "Done. Reboot to start the display:  sudo reboot"
say "Change the link later: edit $CONF, then reboot. Remove: run this script with --uninstall."
