#!/bin/sh

setup_displaymanager() {
	case "${1}" in
		gdm3)
			# autologin + greeter theme
			# timed login required for login after x restart
			if [ "${FLL_AUTOLOGIN}" = "yes" ]; then
				sed -i	-e "/^AutomaticLogin\=.*/d" \
					-e "/^AutomaticLoginEnable\=.*/d" \
					-e "/^TimedLoginEnable\=.*/d" \
					-e "/^TimedLogin\=.*/d" \
					-e "/^TimedLoginDelay\=.*/d" \
					-e "s/^\(\[daemon\]$\)/\1\nAutomaticLogin\=${FLL_LIVE_USER}\nAutomaticLoginEnable\=true\nTimedLoginEnable\=true\nTimedLogin\=${FLL_LIVE_USER}\nTimedLoginDelay\=1/" \
						/etc/gdm3/daemon.conf
			fi

			# reflect this boot's session type both ways (persist keeps the last edit)
			if [ "${FLL_XTYPE}" = "x11" ]; then
				sed -i "s/^#*WaylandEnable=.*/WaylandEnable=false/" /etc/gdm3/daemon.conf
			else
				sed -i "s/^#*WaylandEnable=.*/#WaylandEnable=false/" /etc/gdm3/daemon.conf
			fi

			# preselect the xsession
			cat > /etc/skel/.dmrc <<EOF
[Desktop]
Session=${FLL_DM_SESSION}
EOF
			;;
		lightdm)
			# set autologin user and set timeout to zero
			mkdir -p /etc/lightdm/lightdm.conf.d
			if [ ! -e "/etc/lightdm/lightdm.conf.d/80_${FLL_LIVE_USER}.conf" ]; then
				{
					printf "[SeatDefaults]\ngreeter-hide-users=false\n"
					if [ "${FLL_AUTOLOGIN}" = "yes" ]; then
						printf "autologin-user=%s\nautologin-user-timeout=0\n" \
							"${FLL_LIVE_USER}"
					fi
					printf "autologin-session=%s\n" "${FLL_DM_SESSION}"
				} >"/etc/lightdm/lightdm.conf.d/80_${FLL_LIVE_USER}.conf"
			fi
			;;
		lxdm)
			# set autologin user
			if [ "${FLL_AUTOLOGIN}" = "yes" ] && \
				[ -L /etc/lxdm/default.conf ] && [ ! -e "/etc/lxdm/${FLL_LIVE_USER}.conf" ]; then
				rm -f /etc/lxdm/default.conf
				sed "s/^# autologin=.*/&\nautologin=${FLL_LIVE_USER}/" \
					/etc/lxdm/lxdm.conf > "/etc/lxdm/${FLL_LIVE_USER}.conf"
				ln -fs "${FLL_LIVE_USER}.conf" /etc/lxdm/default.conf
			fi
			;;
		sddm)
			mkdir -p /etc/sddm.conf.d
			SDDM_CONF="/etc/sddm.conf.d/${FLL_LIVE_USER}.conf"
			if [ "${FLL_AUTOLOGIN}" = "yes" ]; then
				grep -q '^\[Autologin\]' "${SDDM_CONF}" 2>/dev/null || \
					printf "\n[Autologin]\nUser=${FLL_LIVE_USER}\nSession=${FLL_DM_SESSION}\nRelogin=true\n" \
						>>"${SDDM_CONF}"
			else
				# encrypted homed home: no autologin; the greeter prompts for the
				# password, which pam_systemd_home uses to unlock the home. The
				# session comes from the home record (--session-launcher). Touch
				# the file so the DisplayServer setting below has a target.
				: >"${SDDM_CONF}"
			fi

			# reflect this boot's session type both ways, not just x11 (persist sticks)
			if grep -q '^DisplayServer=' "${SDDM_CONF}"; then
				sed -i "s/^DisplayServer=.*/DisplayServer=${FLL_XTYPE}/" "${SDDM_CONF}"
			else
				printf '\n[General]\nDisplayServer=%s\n' "${FLL_XTYPE}" >>"${SDDM_CONF}"
			fi
			;;
			slim)
			# set autologin for $FLL_LIVE_USER to yes
			if [ "${FLL_AUTOLOGIN}" = "yes" ]; then
				sed -i	-e "s/^default_user.*/\#FLL\#&/" \
					-e "s/^\#FLL\#\(default_user[ \t]*${FLL_LIVE_USER}$\)/\1/" \
					-e "s/^auto_login.*/\#FLL\#&/" \
					-e "s/^\#FLL\#\(auto_login[ \t]*yes$\)/\1/" \
						/etc/slim.conf
				grep -q ^default_user /etc/slim.conf || \
					printf "default_user\t${FLL_LIVE_USER}\n" >> /etc/slim.conf
				grep -q ^auto_login /etc/slim.conf || \
					printf "auto_login\tyes\n" >> /etc/slim.conf
			fi
		;;
		greetd)
			# uwsm-managed sessions (FLL_DM_SESSION ends in -uwsm) start the
			# compositor via uwsm; everything else runs its bare command.
			case "${FLL_DM_SESSION}" in
				*-uwsm)
					EXECUTE_CMD="uwsm start ${FLL_DM_SESSION%-uwsm}.desktop"
					;;
				*)
					EXECUTE_CMD="${FLL_XSESSION}"
					;;
			esac

			if [ -n "${FLL_XSESSION}" ] && [ -x /usr/bin/gtkgreet ] && \
				[ -x /usr/bin/cage ]; then
				# gtkgreet is graphical and needs a host compositor. cage is a
				# single-window kiosk that exits when gtkgreet finalizes a login,
				# so it hosts the greeter for any session (the host is unrelated
				# to the session gtkgreet launches). One host, no per-compositor
				# config to generate or preserve.
				GTKGREET_STYLE=""
				[ -f /etc/greetd/gtkgreet.css ] && \
					GTKGREET_STYLE=" -s /etc/greetd/gtkgreet.css"
				GREETER_CMD="cage -s -- gtkgreet${GTKGREET_STYLE} -c '${EXECUTE_CMD}'"
			elif [ -n "${FLL_XSESSION}" ] && [ -x /usr/bin/tuigreet ]; then
				TUITHEME="border=magenta;text=cyan;prompt=cyan;time=cyan;action=cyan;button=magenta;container=black;input=magenta"
				GREETER_CMD="/usr/bin/tuigreet --greeting 'Welcome to ${FLL_DISTRO_NAME}'"
				GREETER_CMD="${GREETER_CMD} --time --user-menu --user-menu-max-uid 60513"
				GREETER_CMD="${GREETER_CMD} --asterisks --remember --remember-user-session"
				GREETER_CMD="${GREETER_CMD} --power-shutdown 'systemctl -i poweroff'"
				GREETER_CMD="${GREETER_CMD} --power-reboot 'systemctl -i reboot'"
				GREETER_CMD="${GREETER_CMD} --cmd '${EXECUTE_CMD}' --theme '${TUITHEME}'"
			else
				# agreety: greetd's built-in text greeter, runs on the VT.
				# Full path: greetd execs via /bin/sh whose PATH omits /usr/sbin.
				GREETER_CMD="/usr/sbin/agreety --cmd '${EXECUTE_CMD}'"
			fi

			if [ -n "${GREETER_CMD}" ]; then
				# Only the first command line (default_session); the
				# appended [initial_session] command below is the real
				# session and must survive a second run (persist media).
				sed -i "0,/^command = \".*\"/s#^command = \".*\"#command = \"${GREETER_CMD}\"#" \
					/etc/greetd/config.toml

				# [initial_session] is greetd's autologin; omit it for an
				# encrypted homed home so the greeter prompts to unlock.
				if [ "${FLL_AUTOLOGIN}" = "yes" ] && \
					! grep -q '^\[initial_session\]' /etc/greetd/config.toml; then
					cat >> /etc/greetd/config.toml <<EOF

[initial_session]
command = "${EXECUTE_CMD}"
user = "${FLL_LIVE_USER}"
EOF
				fi
			fi
			;;
	esac
}

setup_desktop() {
	# This function may be called twice for the same desktop if user
	# supplied a desktop= cheatcode - everything below must be idempotent
	case "${1}" in
		*.desktop)
			DESKTOP_FILE="${1}"
			;;
		*)
			if [ "${1#*-*}" = "x11" ]; then
				DESKTOP_FILE=$(find /usr/share/xsessions -type f -iname "${1%-*}*.desktop" \
					| sort | head -n 1)
			elif [ "${1#*-*}" = "wayland" ]; then
				DESKTOP_FILE=$(find /usr/share/wayland-sessions -type f -iname "${1%-*}*.desktop" \
					| sort | head -n 1)
			else
				DESKTOP_FILE=$(find /usr/share/*sessions -type f -iname "${1}.desktop" \
					| sort | head -n 1)
			fi
			if [ ! -f "${DESKTOP_FILE}" ]; then
				DESKTOP_FILE=$(find /usr/share/*sessions -type f -iname "${1%-*}-*.desktop" \
					| sort | head -n 1)
			fi
			if [ ! -f "${DESKTOP_FILE}" ]; then
				DESKTOP_FILE=$(find /usr/share/*sessions -type f -iname "${1}*.desktop" \
					| sort | head -n 1)
			fi
			# failed to determine the "correct" desktop file from desktop= cheatcode.
			# This script is sourced by fll_home, so exiting here would abort live
			# user creation entirely; warn and keep the auto-detected session instead.
			if [ ! -f "${DESKTOP_FILE}" ]; then
				echo "fll_desktop: desktop session file not found for: ${1}, ignoring" >&2
				return 0
			fi
			# update calamares
			DESKTOP_EXEC=$(awk -F= '/^TryExec/{ print $2 }' "${DESKTOP_FILE}")
			if [ -z "${DESKTOP_EXEC}" ]; then
				DESKTOP_EXEC=$(awk -F= '/^Exec/{ print $2 }' "${DESKTOP_FILE}")
			fi
			if [ -n "${DESKTOP_EXEC}" ]; then
				sed -i -e 's/#defaultDesktopEnvironment:/defaultDesktopEnvironment:/' \
					-e "s/^.*executable: \".*\"$/    executable: \"$(basename ${DESKTOP_EXEC% *})\"/" \
					-e "s/^.*desktopFile: \".*\"$/    desktopFile: \"$(basename ${DESKTOP_FILE} .desktop)\"/" \
					/etc/calamares/modules/displaymanager.conf
			fi
			;;
	esac

	# Determine FLL_XTYPE before committing FLL_XSESSION, so a bad desktop=
	# cheatcode falls back to (rather than clobbers) the auto-detected session.
	case "${DESKTOP_FILE}" in
		/usr/share/xsessions/*)
			DESKTOP_XTYPE="x11"
			;;
		/usr/share/wayland-sessions/*)
			DESKTOP_XTYPE="wayland"
			;;
		*)
			echo "fll_desktop: unsupported desktop session: ${DESKTOP_FILE}, ignoring" >&2
			return 0
			;;
	esac
	FLL_XSESSION="$(basename ${DESKTOP_FILE%.desktop})"
	FLL_XTYPE="${DESKTOP_XTYPE}"

	case "${FLL_XSESSION}" in
		lxqt)
			# set window_manager=openbox
			mkdir -p /etc/skel/.config/lxqt
			cp /etc/xdg/lxqt/session.conf \
				/etc/skel/.config/lxqt/session.conf
			;;
		lxqt-wayland)
			# Support various compositors of lxqt (default: labwc)
			case "${1}" in
				lxqt-labwc)
					[ -x /usr/bin/labwc ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/labwc#' \
						/etc/xdg/lxqt/session.conf
					;;
				lxqt-kwin)
					[ -x /usr/bin/kwin_wayland ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/kwin_wayland#' \
						/etc/xdg/lxqt/session.conf
					;;
				lxqt-hyprland)
					[ -x /usr/bin/Hyprland ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/Hyprland#' \
						/etc/xdg/lxqt/session.conf
					;;
				lxqt-miriway)
					[ -x /usr/bin/miriway ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/miriway#' \
						/etc/xdg/lxqt/session.conf
					# startlxqtwayland has no miriway branch, so it falls back
					# to `exec miriway`, which reads ~/.config/miriway-shell.config;
					# seed an LXQt shell there (miriway's own default config is a
					# bare compositor). cp before append keeps this idempotent.
					if [ -f /usr/share/aptosid-settings-lxqt/miriway/miriway-shell.config ]; then
						. /etc/default/keyboard
						mkdir -p /etc/skel/.config
						cp /usr/share/aptosid-settings-lxqt/miriway/miriway-shell.config \
							/etc/skel/.config/miriway-shell.config
						[ "${XKBLAYOUT}" ] && \
							printf 'keymap=%s\n' "${XKBLAYOUT}" \
								>> /etc/skel/.config/miriway-shell.config
					fi
					;;
				lxqt-sway)
					[ -x /usr/bin/sway ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/sway#' \
						/etc/xdg/lxqt/session.conf
					;;
				lxqt-wayfire)
					[ -x /usr/bin/wayfire ] && \
					sed -i 's#^compositor=.*#compositor=/usr/bin/wayfire#' \
						/etc/xdg/lxqt/session.conf
					;;
			esac
			# Solve a chicken and egg problem: preselect wayland compositor
			# or else startlxqt launches lxqt session preferences dialog on
			# first login
			mkdir -p /etc/skel/.config/lxqt
			cp /etc/xdg/lxqt/session.conf \
				/etc/skel/.config/lxqt/session.conf
			# Hack to set initial dark theme
			mkdir -p /etc/skel/.config/labwc
			sed -e 's/Vent/Vent-dark/' \
				/usr/share/lxqt/wayland/labwc/rc.xml \
				> /etc/skel/.config/labwc/rc.xml
			# startlxqtwayland runs labwc with -C ~/.config/labwc, so it
			# never reads /etc/xdg/labwc/environment. Seed the cursor from
			# lxqt's [Mouse] section so the wayland session matches the rest.
			sed -n	-e 's/^cursor_size=/XCURSOR_SIZE=/p' \
				-e 's/^cursor_theme=/XCURSOR_THEME=/p' \
				/etc/xdg/lxqt/session.conf \
				> /etc/skel/.config/labwc/environment

			# Override startlxqtwayland's first-login defaults (it guesses the
			# keymap from $LANG and ships the LXQt wallpaper). Seed each
			# compositor config into /etc/skel with the live keyboard layout
			# and the aptosid wallpaper/cursor; startlxqtwayland then keeps our
			# copy. sed-from-source keeps this idempotent.
			. /etc/default/keyboard
			cursor_theme=$(sed -n 's/^cursor_theme=//p' /etc/xdg/lxqt/session.conf)
			cursor_size=$(sed -n 's/^cursor_size=//p' /etc/xdg/lxqt/session.conf)
			wallpaper=/usr/share/wallpapers/aptosid-nemesis-wide.png
			wayland_dir=/usr/share/lxqt/wayland
			skel_wayland=/etc/skel/.config/lxqt/wayland
			mkdir -p "${skel_wayland}"
			# labwc: add the live keyboard to the environment seeded above and a
			# wallpaper autostart (the dir now exists, so startlxqtwayland won't
			# copy its own).
			printf 'XKB_DEFAULT_LAYOUT=%s\nXKB_DEFAULT_VARIANT=%s\nXKB_DEFAULT_MODEL=%s\nXKB_DEFAULT_OPTIONS=%s\n' \
				"${XKBLAYOUT}" "${XKBVARIANT}" "${XKBMODEL}" "${XKBOPTIONS}" \
				>> /etc/skel/.config/labwc/environment
			[ -f "${wayland_dir}/labwc/autostart" ] && \
				sed "s#/usr/share/lxqt/wallpapers/[^ \"]*\.png#${wallpaper}#g" \
					"${wayland_dir}/labwc/autostart" \
					> /etc/skel/.config/labwc/autostart
			# sway (native output bg; quoted xkb like aptosid's sway config)
			[ -f "${wayland_dir}/lxqt-sway.config" ] && {
				sed -e "s#/usr/share/lxqt/wallpapers/[^ \"]*\.png#${wallpaper}#g" \
					-e "s#^[[:space:]]*xkb_layout .*#    xkb_layout \"${XKBLAYOUT}\"\n    xkb_variant \"${XKBVARIANT}\"#" \
					-e "s#^[[:space:]]*xkb_options .*#    xkb_options \"${XKBOPTIONS}\"#" \
					"${wayland_dir}/lxqt-sway.config" \
					> "${skel_wayland}/lxqt-sway.config"
				[ "${cursor_theme}" ] && \
					printf 'seat * xcursor_theme %s %s\n' "${cursor_theme}" "${cursor_size}" \
						>> "${skel_wayland}/lxqt-sway.config"
			}
			# wayfire
			[ -f "${wayland_dir}/lxqt-wayfire.ini" ] && \
				sed -e "s#/usr/share/lxqt/wallpapers/[^ \"]*\.png#${wallpaper}#g" \
					-e "s/^xkb_layout =.*/xkb_layout = ${XKBLAYOUT}/" \
					-e "s/^xkb_variant =.*/xkb_variant = ${XKBVARIANT}/" \
					-e "s/^xkb_options =.*/xkb_options = ${XKBOPTIONS}/" \
					-e "s/^cursor_theme =.*/cursor_theme = ${cursor_theme}/" \
					-e "s/^cursor_size =.*/cursor_size = ${cursor_size}/" \
					"${wayland_dir}/lxqt-wayfire.ini" \
					> "${skel_wayland}/lxqt-wayfire.ini"
			# hyprland (startlxqtwayland uses the .lua unless a .conf exists)
			[ -f "${wayland_dir}/lxqt-hyprland.lua" ] && \
				sed -e "s#/usr/share/lxqt/wallpapers/[^ \"]*\.png#${wallpaper}#g" \
					-e "s/kb_layout  *= \"[^\"]*\"/kb_layout = \"${XKBLAYOUT}\"/" \
					-e "s/kb_variant  *= \"[^\"]*\"/kb_variant = \"${XKBVARIANT}\"/" \
					"${wayland_dir}/lxqt-hyprland.lua" \
					> "${skel_wayland}/lxqt-hyprland.lua"
			;;
		labwc)
			. /etc/default/keyboard
			if [ "${XKBVARIANT}" ]; then
				XKB_DEFAULT_LAYOUT="${XKBLAYOUT}(${XKBVARIANT})"
			else
				XKB_DEFAULT_LAYOUT="${XKBLAYOUT}"
			fi
			if ! grep -q '^XKB_DEFAULT_LAYOUT=' /etc/xdg/labwc/environment; then
				cat >> /etc/xdg/labwc/environment <<EOF
XKB_DEFAULT_LAYOUT="${XKB_DEFAULT_LAYOUT}"
EOF
			fi
			;;
		hyprland|hyprland-uwsm)
			# Hyprland reads its default config from /etc/xdg/hypr/hyprland.lua
			# (shipped by aptosid-settings-hyprland), so /etc/skel needs no
			# seeding. That config leaves kb_layout empty; the shared helper
			# writes the live keyboard layout into a uwsm env drop-in as
			# XKB_DEFAULT_* (the same helper calamares runs post-install).
			[ -x /usr/libexec/aptosid-settings-hyprland/keyboard-env ] && \
				/usr/libexec/aptosid-settings-hyprland/keyboard-env
			;;
		sway)
			mkdir -p /etc/skel/.config/sway
			cp /usr/share/aptosid-settings-sway/config /etc/skel/.config/sway
			cp /usr/share/aptosid-settings-sway/colorscheme /etc/skel/.config/sway
			. /etc/default/keyboard
			sed -i "s#xkb_layout \"\"#xkb_layout \"${XKBLAYOUT}\"#" /etc/skel/.config/sway/config
			sed -i "s#xkb_variant \"\"#xkb_variant \"${XKBVARIANT}\"#" /etc/skel/.config/sway/config
			sed -i "s#xkb_model \"\"#xkb_model \"${XKBMODEL}\"#" /etc/skel/.config/sway/config
			sed -i "s#xkb_options \"\"#xkb_options \"${XKBOPTIONS}\"#" /etc/skel/.config/sway/config
			;;
	esac
}

# detect and setup all installed desktops
for desktop_file in /usr/share/*sessions/*.desktop; do
	[ -f "${desktop_file}" ] && setup_desktop "${desktop_file}"
done

# setup active desktop
for opt in $(cat /proc/cmdline); do
	case "${opt}" in
		desktop=*)
			setup_desktop "${opt#desktop=}"
			;;
	esac
done

# display managers should launch the uwsm-managed session whenever a
# <session>-uwsm.desktop is shipped, so the compositor runs as a proper systemd
# session and picks up /etc/environment.d and /etc/xdg/uwsm/env (and the socket-
# activated pipewire/portals under graphical-session.target). Any session opts
# in just by providing that variant -- Hyprland, Sway, labwc and cage kiosks
# alike, with no per-compositor list to maintain here. FLL_XSESSION is left
# as-is for the skel config above; only the display manager session changes.
FLL_DM_SESSION="${FLL_XSESSION}"
if [ -f "/usr/share/wayland-sessions/${FLL_XSESSION}-uwsm.desktop" ]; then
	FLL_DM_SESSION="${FLL_XSESSION}-uwsm"
fi

# configure displaymanager
for displaymanager in greetd slim lxdm lightdm gdm3 sddm; do
	command -v "${displaymanager}" >/dev/null 2>&1 || continue
	echo "Configuring ${displaymanager}..."
	setup_displaymanager "${displaymanager}"
done
