#!/bin/bash
set -euo pipefail

THIS_COMMAND=$(basename "$0")
IMG_MAGICK="magick"
SERVICE_NAME="swaybg.service"

WP_DIR="${XDG_CACHE_HOME:-$HOME/.cache}"
WP_FILE="$WP_DIR/wallpaper"
BLUR_WP="$WP_DIR/wallpaper_blur"

usage() {
  cat << EOF
Usage: $THIS_COMMAND [-d output_path] image1 image2 ...
Options:
  -d, --dir OUTPUT_PATH   Directory to store chosen image. (default: $WP_DIR)
  -h, --help              Show this help message and exit.
Notes:
  - This script needs 'swaybg.service' to be set up for overview background support (unless awww #521 solved). See niri documentation for details.
  - Web URLs are also supported (via 'curl' or 'wget' downloading).
  - If multiple images are provided, one will be randomly picked each time the script is executed.
EOF
  exit 1
}

# showing help shouldn't require any dependencies.
while [[ $# -gt 0 ]]; do
  case "$1" in
    -d|--dir)
      if [[ $# -lt 2 ]]; then echo "Missing argument for $1"; usage; fi
      WP_DIR="$2"; shift 2 ;;
    -h|--help)
      usage ;;
    --)
      shift; break ;;
    -*)
      echo "Unknown option: $1"; usage ;;
    *)
      break ;;
  esac
done

if ! command -v awww >/dev/null 2>&1; then
  echo "x) 'awww' not found. Unable to comply." >&2
  exit 2
fi

if command -v magick >/dev/null 2>&1; then
  IMG_MAGICK="magick"
elif command -v convert >/dev/null 2>&1; then
  IMG_MAGICK="convert"
else
  echo "x) 'magick' or 'convert' not found. Image processing unavailable." >&2
  exit 2
fi

set_wallpaper() {
  fsize=$($IMG_MAGICK identify -format "%w %h" -- "$1" 2>/dev/null) || {
    echo "Invalid image file." >&2
    exit 10
  }
  finput=$1

  read -r fw fh <<< "$fsize"
  (( fw > 3840 && fh > 2160 )) && {
    finput=$(mktemp "${TMPDIR:-/tmp}/chbg.XXXXXXXX.webp")
    trap 'rm -f "$finput"' EXIT
    echo " -> image too large, resizing ..."
    # echo "DEBUG: resized image at $finput"
    $IMG_MAGICK "$1" -resize "3840x2160^" \
      -quality 90 \
      -define webp:method=6 \
      -define webp:alpha-quality=100 "$finput"
  }

  echo -n " -> making blurred version of '${1##*/}' ... "
  cp "$finput" "$WP_FILE"
  $IMG_MAGICK "$WP_FILE" -filter Gaussian -blur 0x30 "$BLUR_WP"
  echo "Done."

  awww img "$WP_FILE" --transition-type=random

  if [[ -f "$HOME/.config/systemd/user/niri.service.wants/$SERVICE_NAME" ]]; then
    echo " -> restarting $SERVICE_NAME ..."
    systemctl --user restart "$SERVICE_NAME"
  else
    echo " !) '$SERVICE_NAME' didn't loaded by niri. Won't reload backdrop." >&2
    echo "  => See niri documentation for setting up swaybg systemd unit." >&2
    echo "  => Or wait for awww #521 on codeberg being resolved." >&2
    exit 1
  fi
}

imagepool=()
lastresult=""

# Read from stdin if data is available
if [ ! -t 0 ]; then
  while IFS= read -r line; do
    imagepool+=("$line")
  done
fi

# Read from positional arguments
for arg in "$@"; do
  imagepool+=("$arg")
done

if [ ${#imagepool[@]} -eq 0 ]; then
  echo "No images provided." >&2
  exit 1
fi

mkdir -p -- "$WP_DIR" "/tmp/$USER"

if [ -f "/tmp/$USER/chbg.last-slide.log" ]; then
  lastresult=$(cat "/tmp/$USER/chbg.last-slide.log")
fi

# Select a random image from the pool and set it as wallpaper
while : ; do
  randomimage="${imagepool[RANDOM % ${#imagepool[@]}]}"
  if [[ "$randomimage" == "http://"* || "$randomimage" == "https://"* ]]; then
    break
  fi

  if [ "$randomimage" != "$lastresult" ] || [ ${#imagepool[@]} -eq 1 ]; then
    echo "$randomimage" > "/tmp/$USER/chbg.last-slide.log"
    break
  fi
done

echo "Selected: $randomimage"

request_wallpaper() {
  tmpfile=$(mktemp)
  trap 'rm -f "$tmpfile"' EXIT
  if command -v curl >/dev/null 2>&1; then
    curl -sSL "$1" -o "$tmpfile"
  elif command -v wget >/dev/null 2>&1; then
    wget -qO "$tmpfile" "$1"
  else
    echo "x) Unable to fetch image without 'curl' or 'wget'." >&2
    exit 2
  fi
  set_wallpaper "$tmpfile"
}

if [ -f "$randomimage" ]; then
  set_wallpaper "$randomimage"
else
  request_wallpaper "$randomimage"
fi
