#!/bin/sh

# Wrap a string as a GVariant text-format string literal,
# escaping backslashes and single quotes per the GVariant syntax.
gvariant_string() {
  printf "'%s'" "$(printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e "s/'/\\\\'/g")"
}

# Print $2 to stderr (with backslash escapes like \n interpreted), wrapped in the ANSI SGR
# code $1 when stderr is a TTY.
print_color() {
  if [ -t 2 ]; then
    printf '\033[%sm%b\033[0m\n' "$1" "$2" >&2
  else
    printf '%b\n' "$2" >&2
  fi
}

# Send an action to the running Ulauncher instance and exit. ServiceUnknown means nothing owns
# the bus name and no service file can activate it, which both come down to "it isn't running".
send_action() {
  # Only capture stderr after a failure - it costs a subshell, and a failed action delivered
  # nothing, so repeating it changes nothing.
  if gapplication action io.ulauncher.Ulauncher "$@" 2>/dev/null; then
    exit 0
  fi

  action_error=$(gapplication action io.ulauncher.Ulauncher "$@" 2>&1 >/dev/null)
  action_status=$?
  if [ "$action_status" -eq 0 ]; then
    exit 0
  fi
  case "$action_error" in
    *ServiceUnknown*)
      print_color 33 "Ulauncher is not running.\nStart it with \`ulauncher start\`, or run it on login with \`systemctl --user enable --now ulauncher\`." ;;
    *)
      printf '%s\n' "$action_error" >&2 ;;
  esac
  exit "$action_status"
}

# Rewrite legacy flags before any further argv handling. Direct `python -m ulauncher`
# invocations bypass this and get argparse's "unrecognized arguments" error instead.
orig_count=$#
walked=0
while [ "$walked" -lt "$orig_count" ]; do
  arg=$1; shift; walked=$((walked + 1))
  case "$arg" in
    # --autostart-method-xdg exists only to tell Ulauncher v6 that it was started from Ulauncher v5 desktop entry
    # (likely via xdg autostart), and that we should refuse to start so the bus name isn't taken before the systemd
    # unit claims it. However it was added to v5 first in v5.16.0. Before then `--hide-window` was in the v5 desktop
    # entry, so we need to reject both.
    --autostart-method-xdg)
      print_color 33 "The --autostart-method-xdg argument has been removed"; exit 2 ;;
    --hide-window)
      print_color 33 "The --hide-window argument has been removed (use start)"; exit 2 ;;
    --no-extensions)
      print_color 33 "The --no-extensions argument has been removed (see --help for available commands)"; exit 2 ;;
    --no-window-shadow)
      print_color 33 "The --no-window-shadow argument has been removed (configure via the Window shadow size setting in preferences)"; exit 2 ;;
    --dev)
      print_color 33 "The --dev argument has been removed (use --verbose)"; set -- "$@" --verbose ;;
    --daemon)
      print_color 33 "The --daemon argument has been removed (use start)"; set -- "$@" start ;;
    --no-window)
      print_color 33 "The --no-window argument has been removed (use start)"; set -- "$@" start ;;
    *) set -- "$@" "$arg" ;;
  esac
done

# Fast path: bypass Python for the performance-critical commands (bare invocation, `show`,
# `show <query>`, `toggle`). Any flag, unknown subcommand, or extra positional defers to
# Python so it can produce the real parse output/error.
subcmd=''
query=''
has_query=0
needs_argparse=0
for arg in "$@"; do
  case "$arg" in
    -*) needs_argparse=1 ;;
    *)
      if [ -z "$subcmd" ]; then
        subcmd=$arg
      elif [ "$subcmd" = show ] && [ "$has_query" -eq 0 ]; then
        query=$arg; has_query=1
      else
        needs_argparse=1
      fi
      ;;
  esac
done

if [ "$needs_argparse" -eq 0 ]; then
  case "$subcmd" in
    '')
      # D-Bus would activate the installed Ulauncher rather than this checkout. Skipping readlink
      # keeps forks off the fast path, at the cost of missing a checkout reached via a symlink.
      if [ -d "${0%/*}/../ulauncher" ] && [ "$(gdbus call --session --dest org.freedesktop.DBus \
        --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.NameHasOwner \
        io.ulauncher.Ulauncher 2>/dev/null)" != "(true,)" ]; then
        print_color 33 "No Ulauncher instance is running - starting this checkout."
        exec "$0" start
      fi
      send_action show-window ;;
    toggle)  send_action toggle-window ;;
    show)
      if [ "$has_query" -eq 1 ]; then
        send_action set-query "$(gvariant_string "$query")"
      else
        send_action show-window
      fi
      ;;
  esac
fi

SCRIPT_PATH=$(readlink -f "$0")
PROJECT_ROOT=$(dirname "$(dirname "$SCRIPT_PATH")")

if [ -d "$PROJECT_ROOT/ulauncher" ]; then
  # Running from a dev checkout.
  export PYTHONPATH="${PROJECT_ROOT}${PYTHONPATH:+:$PYTHONPATH}"
  export ULAUNCHER_SYSTEM_DATA_DIR="$PROJECT_ROOT/data"
else
  # paths.py previously derived the install prefix from sys.argv[0] (= /usr/bin/ulauncher),
  # but `python3 -m ulauncher` makes sys.argv[0] point into site-packages. Pass it explicitly.
  : "${ULAUNCHER_SYSTEM_PREFIX:=$PROJECT_ROOT}"
  export ULAUNCHER_SYSTEM_PREFIX
fi

python3 -m ulauncher "$@"
status=$?

if [ "$status" -ne 0 ] && [ -f /etc/arch-release ] && ! python3 -c 'import ulauncher' 2>/dev/null; then
  arch_pkg_found=0
  for arch_pkg in /usr/lib/python*/site-packages/ulauncher; do
    [ -d "$arch_pkg" ] || continue
    arch_pkg_found=1
    export PYTHONPATH="$(dirname "$arch_pkg")${PYTHONPATH:+:$PYTHONPATH}"
  done
  if [ "$arch_pkg_found" -eq 1 ]; then
    print_color '1;31' 'Your Arch Linux system Python version is updated after installing Ulauncher.\nPlease do a clean reinstall of Ulauncher, and any other AUR packages that may be affected by this.\nFor more info, see https://github.com/Ulauncher/Ulauncher/discussions/1280'
    exec python3 -m ulauncher "$@"
  fi
fi

exit "$status"
