#!/bin/zsh
setopt no_unset extended_glob warn_create_global
typeset -g DSTROOT DISPLAYNUM REPO_ROOT
set -x
DSTROOT=$1
DISPLAYNUM=$2
REPO_ROOT=${0:P:h:h}

# helpers
die() {
	printf >&2 '%s\n' "$@"
	exit 1
}

ensure-container-started() {
	[[ $1 == */* ]] && die "Invalid container name: ${(qqq)1}"
	s6-svc -wU -T 4000 -o /run/service/container.$1
}

to-current-inbox() {
	local from_container=$1
	shift
	ensure-container-started $from_container
	link-to-container-inbox $from_container ${DSTROOT:t} "$@" || exit $?
}

# Copy over the versioned filesystem image
copy-skel() {
	local skel dst
	s6-hiercopy $REPO_ROOT/xsession-skel/homedir $DSTROOT/home/$USER || exit $?
	for skel in $REPO_ROOT/xsession-skel/*/*(DN); do
		[[ ${skel:h:t} == homedir ]] && continue
		dst=$DSTROOT/${skel:h:t}/${skel:t}
		s6-hiercopy $skel $dst || exit $?
	done
}

# make files that can't be easily version-controlled
setup-special() {
	# FIFO for plumber
	local fifo=/run/user/$UID/plumber_fifo.X$DISPLAYNUM
	if ! [[ -p $fifo ]]; then
		mkfifo $fifo || exit $?
	fi
	ln -f $fifo $DSTROOT/run/plumber_fifo || exit $?

	# init symplink for container startup
	ln -sf /home/$USER/run $DSTROOT/run/user-run || exit $?
	ln -sf user-run/init $DSTROOT/run/init || exit $?
}

# make X server available to the xsession container
setup-x11() {
	s6-svwait /run/service/container.X$DISPLAYNUM || exit $?

	#ls -lhA --full-time /run /run/containers /run/containers/X$DISPLAYNUM.xorg/tmp  /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix $DSTROOT $DSTROOT/run

	cp -v /run/Xauthority.$DISPLAYNUM $DSTROOT/run/Xauthority.$DISPLAYNUM || exit $?
	#ln -f /run/Xauthority.$DISPLAYNUM $DSTROOT/run/Xauthority.$DISPLAYNUM || exit $?
	printf '%s' >$DSTROOT/home/$USER/run/env/XAUTHORITY /run/Xauthority.$DISPLAYNUM || exit $?

	ln -f /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix/X$DISPLAYNUM $DSTROOT/tmp/.X11-unix/X$DISPLAYNUM || exit $?
	printf '%s' >$DSTROOT/home/$USER/run/env/DISPLAY :$DISPLAYNUM || exit $?
}

# launch container for xpra and make X server available to it
setup-xpra() {
	to-current-inbox xpra.$USER run/exec/x11 run/exec/exec || exit $?
	return  # TODO: the rest is probably unnecessary, delete if not needed
	local svstat xpra_svc xpra_dir
	xpra_svc=/run/service/container.xpra.$USER
	xpra_dir=/run/containers/xpra.$USER
	svstat=$(s6-svstat -ur $xpra_svc)
	if (($!)); then
		echo >&2 "Warning: could not read status of service: $xpra_svc"
		return
	fi
	if [[ $svstat != 'true true' ]]; then
		echo >&2 "Warning: service not up and running: $xpra_svc"
		return
	fi

	cp -v /run/Xauthority.$DISPLAYNUM $xpra_dir/run/Xauthority.$DISPLAYNUM || exit $?
	#printf '%s' >$DSTROOT/home/$USER/run/env/XAUTHORITY /run/Xauthority.$DISPLAYNUM || exit $?
	ln -f /run/containers/X$DISPLAYNUM.xorg/tmp/.X11-unix/X$DISPLAYNUM $xpra_dir/tmp/.X11-unix/X$DISPLAYNUM || exit $?
}

# launch container for handling passwords
setup-pass() {
	to-current-inbox pass.$USER run/pass/list run/exec/exec || exit $?
}

# link sockets for uncontainerized helpers
setup-helper-sockets() {
	local sock
	s6-rc -l /run/user/$USER/s6-rc -u change xsession-all || exit $?
	for sock in /run/user/$USER/xsession/*(=); do
		ln -f $sock $DSTROOT/run/${sock:t}.s || exit $?
	done
}

main() {
	if ! [[ -d $DSTROOT ]]; then
		echo >&2 "Destination root not a directory: $DSTROOT"
		exit 2
	fi

	if [[ $DISPLAYNUM != [0-9] ]]; then
		echo >&2 "Invalid display number: $DISPLAYNUM"
		exit 3
	fi

	copy-skel || exit $?
	setup-special || exit $?
	setup-x11 || exit $?
	setup-xpra || exit $?
	setup-pass || exit $?
	setup-helper-sockets || exit $?
}

main