#!/usr/bin/env bash
set -euo pipefail
session_target_started=0
shell_pid=
agent_pid=
autostart_pid=
manage_session=0
if [[ ${FERESE_SESSION_MODE:-desktop} == desktop && ${FERESE_SESSION_IMPORT_ENV:-0} == 1 ]]; then
    manage_session=1
fi
cleanup() {
    trap - EXIT INT TERM
    if [[ -n $autostart_pid ]]; then
        kill "$autostart_pid" 2>/dev/null || true
        wait "$autostart_pid" 2>/dev/null || true
    fi
    if [[ -n $shell_pid ]]; then kill "$shell_pid" 2>/dev/null || true; fi
    if [[ -n $agent_pid ]]; then
        kill "$agent_pid" 2>/dev/null || true
        wait "$agent_pid" 2>/dev/null || true
    fi
    if ((session_target_started)); then
        systemctl --user stop ferese-session.target || true
    fi
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

# The compositor supplies its new Wayland socket before this helper starts.
# Nested previews must never replace the host session's activation environment.
if ((manage_session)); then
    # Shell control uses a private socket FD. Activation must use the public
    # socket so portal and other desktop services connect as ordinary clients.
    public_display=${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}
    # Empty assignments replace stale values; D-Bus cannot remove activation variables.
    activation_vars=(
        "WAYLAND_DISPLAY=$public_display"
        "DISPLAY=${DISPLAY:-}"
        "XAUTHORITY=${XAUTHORITY:-}"
        "FERESE_SOCKET=${FERESE_SOCKET:-}"
        XDG_CURRENT_DESKTOP
        XDG_SESSION_DESKTOP
        XDG_SESSION_TYPE
    )
    if command -v dbus-update-activation-environment >/dev/null; then
        if ! env WAYLAND_DISPLAY="$public_display" \
            dbus-update-activation-environment --systemd "${activation_vars[@]}"; then
            env WAYLAND_DISPLAY="$public_display" \
                dbus-update-activation-environment "${activation_vars[@]}" || true
        fi
    fi
    # User buses can outlive logout and may predate a newly installed service directory.
    if command -v dbus-send >/dev/null; then
        dbus-send --session --type=method_call --print-reply \
            --dest=org.freedesktop.DBus /org/freedesktop/DBus \
            org.freedesktop.DBus.ReloadConfig >/dev/null || true
    fi
    if command -v systemctl >/dev/null; then
        systemctl --user daemon-reload || true
        if systemctl --user start ferese-session.target; then
            session_target_started=1
            # A user manager can retain the target across session transitions.
            # Refresh an already-running portal after importing this session's
            # environment so it uses the installed release and current display.
            systemctl --user try-restart xdg-desktop-portal-ferese.service || true
        else
            echo 'Ferese: graphical session target could not start; portal activation may be unavailable.' >&2
        fi
    fi
fi
release_dir=$(dirname -- "$(readlink -f -- "$0")")
# Agent failures must not take down a healthy shell. The compositor supervises
# this helper (and creates fresh private connections) when the shell itself exits.
supervise_agent() {
    local child= delay=1 started
    trap 'trap - TERM INT; if [[ -n $child ]]; then kill "$child" 2>/dev/null || true; wait "$child" 2>/dev/null || true; fi; exit 0' TERM INT
    while true; do
        started=$SECONDS
        env -u WAYLAND_SOCKET -u FERESE_SHELL_CONTROL_SOCKET \
            WAYLAND_DISPLAY="${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}" \
            "$release_dir/ferese-polkit-agent" &
        child=$!
        wait "$child" || true
        child=
        if ((SECONDS - started >= 60)); then delay=1; fi
        sleep "$delay" &
        child=$!
        wait "$child" || true
        child=
        if ((delay < 30)); then delay=$((delay * 2)); fi
        if ((delay > 30)); then delay=30; fi
    done
}
supervise_agent &
agent_pid=$!
"$release_dir/ferese-shell" &
shell_pid=$!
if ((manage_session)) && [[ ${FERESE_CLIENT_RESTART:-0} != 1 && -x $release_dir/feresectl ]]; then
    env WAYLAND_DISPLAY="${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}" \
        "$release_dir/feresectl" autostart &
    autostart_pid=$!
fi
if wait "$shell_pid"; then
    status=0
else
    status=$?
fi
exit "$status"
