#!/usr/bin/bash
#
# Launch a HyprCosmic session: cosmic-comp for window management, HyDE's shell
# on top.
#
# Deliberately separate from /usr/bin/start-cosmic rather than patching it.
# The stock COSMIC session entry keeps working untouched, so a broken
# HyprCosmic config is always one logout away from being escaped — which
# matters when the thing you are replacing is your desktop.

set -e

# The forked binaries, installed alongside rather than over the stock ones.
#
# Pointing at /usr/bin/cosmic-session here would be a silent no-op: the system
# binary has no profile module, so the session would come up as ordinary COSMIC
# and the gating would look broken. Installing to a private prefix instead of
# replacing /usr/bin also means `dnf update cosmic-session` cannot clobber the
# fork, and the stock session entry keeps working as the escape hatch.
HYPRCOSMIC_SESSION_BIN="${HYPRCOSMIC_SESSION_BIN:-/usr/libexec/hyprcosmic/cosmic-session}"
HYPRCOSMIC_COMP_BIN="${HYPRCOSMIC_COMP_BIN:-/usr/libexec/hyprcosmic/cosmic-comp}"

if [[ ! -x "$HYPRCOSMIC_SESSION_BIN" ]]; then
    echo "start-hyprcosmic: $HYPRCOSMIC_SESSION_BIN is missing or not executable" >&2
    echo "start-hyprcosmic: log out and choose the stock COSMIC session" >&2
    exit 1
fi

# Capture this session's output to a file that outlives it.
#
# A session that fails drops you straight back to the greeter, taking its
# stderr with it -- and by then you cannot read the journal from inside a
# session that no longer exists. A plain file in the cache directory is still
# there afterwards, whatever happened.
#
# A plain redirect, not `tee` into a process substitution: tee would be a child
# process the session writes through, so if it ever died the session would take
# a SIGPIPE. Nothing about diagnostics should be able to kill the desktop.
#
# Every step is guarded. If any of it fails the session starts anyway with no
# log -- losing diagnostics is an inconvenience, refusing to log in is not.
#
# The previous log is kept as .1, so a second attempt does not erase the
# evidence from the first.
HYPRCOSMIC_LOG="${XDG_CACHE_HOME:-$HOME/.cache}/hyprcosmic/session.log"
if mkdir -p "$(dirname "$HYPRCOSMIC_LOG")" 2>/dev/null; then
    if [[ -f "$HYPRCOSMIC_LOG" ]]; then
        mv -f "$HYPRCOSMIC_LOG" "${HYPRCOSMIC_LOG}.1" 2>/dev/null || true
    fi
    if : >>"$HYPRCOSMIC_LOG" 2>/dev/null; then
        exec >>"$HYPRCOSMIC_LOG" 2>&1
        echo "=== hyprcosmic session starting $(date -Is) ==="
        echo "    session bin: $HYPRCOSMIC_SESSION_BIN"
        echo "    comp bin:    $HYPRCOSMIC_COMP_BIN"
        echo "    autostart:   ${XDG_CONFIG_HOME:-$HOME/.config}/hyprcosmic/autostart"
    fi
fi

# Selects the component set in cosmic-session's profile module: cosmic-panel,
# cosmic-launcher, cosmic-app-library, cosmic-workspaces, cosmic-bg and
# cosmic-files-applet are skipped; waybar and friends come from
# ~/.config/hyprcosmic/autostart.
export HYPRCOSMIC_PROFILE=hyprcosmic

# Keep COSMIC's identity: portals, cosmic-settings and any COSMIC app still
# key off this, and the compositor underneath really is COSMIC.
export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-COSMIC}"
export XDG_SESSION_DESKTOP="${XDG_SESSION_DESKTOP:-hyprcosmic}"

# Same hygiene as start-cosmic: a failed unit left by a previous graphical
# session will otherwise block this one from starting.
if command -v systemctl >/dev/null; then
    for unit in $(systemctl --user --no-legend --state=failed --plain list-units | cut -f1 -d' '); do
        partof="$(systemctl --user show -p PartOf --value "$unit")"
        for target in cosmic-session.target graphical-session.target; do
            if [ "$partof" = "$target" ]; then
                systemctl --user reset-failed "$unit"
                break
            fi
        done
    done
fi

# cosmic-session takes the compositor to launch as its first argument
# (main.rs: `args.next().unwrap_or_else(|| String::from("cosmic-comp"))`),
# which is how a forked cosmic-comp gets used without replacing the system one.
if [[ -z "${DBUS_SESSION_BUS_ADDRESS}" ]]; then
    exec /usr/bin/dbus-run-session -- "${HYPRCOSMIC_SESSION_BIN}" "${HYPRCOSMIC_COMP_BIN}"
else
    exec "${HYPRCOSMIC_SESSION_BIN}" "${HYPRCOSMIC_COMP_BIN}"
fi
