#!/bin/bash
set -euo pipefail

: "${XDG_CONFIG_HOME:=${HOME}/.config}"
: "${XDG_CACHE_HOME:=${HOME}/.cache}"
: "${XDG_DATA_HOME:=${HOME}/.local/share}"
: "${XDG_RUNTIME_DIR:=/run/user/${UID}}"

# Redirect TMPDIR to real disk storage so downloads/unpacking don't hit the 5GB RAM tmpfs
export TMPDIR="${XDG_CACHE_HOME}/unityhub/tmp"
export UNITY_DATADIR="${XDG_DATA_HOME}"

mkdir -p \
	"${XDG_CONFIG_HOME}"/unity \
	"${XDG_CONFIG_HOME}"/unity3d \
	"${XDG_CONFIG_HOME}"/unityhub \
	"${XDG_CONFIG_HOME}"/UnityHub \
	"${XDG_CACHE_HOME}"/unity \
	"${XDG_CACHE_HOME}"/unityhub/tmp \
	"${XDG_CACHE_HOME}"/UnityHub \
	"${XDG_DATA_HOME}"/unity3d \
	"${XDG_DATA_HOME}"/Unity \
	"${HOME}"/Unity

BWRAP_ARGS=(
	--unshare-all
	--share-net
	--die-with-parent
	--new-session

	# System root & base binaries
	--ro-bind /usr /usr
	--ro-bind /bin /bin
	--ro-bind /lib /lib
	--ro-bind-try /lib64 /lib64
	--ro-bind-try /opt /opt
	--dev /dev
	--proc /proc
	--tmpfs /tmp

	# Hardware acceleration (DRI / GPU & shared memory)
	--dev-bind-try /dev/dri /dev/dri
	--bind-try /dev/shm /dev/shm
	--ro-bind-try /sys/dev/char /sys/dev/char
	--ro-bind-try /sys/devices /sys/devices

	# Dynamic linker cache & configuration
	--ro-bind-try /etc/ld.so.cache /etc/ld.so.cache
	--ro-bind-try /etc/ld.so.conf /etc/ld.so.conf
	--ro-bind-try /etc/ld.so.conf.d /etc/ld.so.conf.d
	--ro-bind-try /etc/alternatives /etc/alternatives

	# GUI, fonts & hardware configuration
	--ro-bind-try /tmp/.X11-unix /tmp/.X11-unix
	--ro-bind-try /etc/fonts /etc/fonts
	--ro-bind-try /etc/drirc /etc/drirc
	--ro-bind-try /etc/drirc.d /etc/drirc.d
	--ro-bind-try /etc/vulkan /etc/vulkan
	--ro-bind-try /etc/glvnd /etc/glvnd
	--ro-bind-try /etc/machine-id /etc/machine-id

	# Network resolution & system identity (Node.js getpwuid_r requirement)
	--ro-bind-try /etc/passwd /etc/passwd
	--ro-bind-try /etc/group /etc/group
	--ro-bind-try /etc/resolv.conf /etc/resolv.conf
	--ro-bind-try /run/systemd/resolve /run/systemd/resolve
	--ro-bind-try /etc/hosts /etc/hosts
	--ro-bind-try /etc/os-release /etc/os-release
	--ro-bind-try /etc/gentoo-release /etc/gentoo-release
	--ro-bind-try /etc/localtime /etc/localtime

	# TLS/SSL certificates
	--ro-bind-try /etc/ssl /etc/ssl
	--ro-bind-try /etc/ca-certificates /etc/ca-certificates
	--ro-bind-try /usr/share/ca-certificates /usr/share/ca-certificates
	--ro-bind-try /etc/pki /etc/pki

	# Sandboxed HOME
	--tmpfs "${HOME}"
	--bind "${XDG_CONFIG_HOME}"/unity "${XDG_CONFIG_HOME}"/unity
	--bind "${XDG_CONFIG_HOME}"/unity3d "${XDG_CONFIG_HOME}"/unity3d
	--bind "${XDG_CONFIG_HOME}"/unityhub "${XDG_CONFIG_HOME}"/unityhub
	--bind "${XDG_CONFIG_HOME}"/UnityHub "${XDG_CONFIG_HOME}"/UnityHub
	--bind "${XDG_CACHE_HOME}"/unity "${XDG_CACHE_HOME}"/unity
	--bind "${XDG_CACHE_HOME}"/unityhub "${XDG_CACHE_HOME}"/unityhub
	--bind "${XDG_CACHE_HOME}"/UnityHub "${XDG_CACHE_HOME}"/UnityHub
	--bind "${XDG_DATA_HOME}"/unity3d "${XDG_DATA_HOME}"/unity3d
	--bind "${XDG_DATA_HOME}"/Unity "${XDG_DATA_HOME}"/Unity
	--bind "${HOME}"/Unity "${HOME}"/Unity

	# Git & SSH config
	--ro-bind-try "${HOME}"/.gitconfig "${HOME}"/.gitconfig
	--ro-bind-try "${XDG_CONFIG_HOME}"/git "${XDG_CONFIG_HOME}"/git
	--ro-bind-try "${HOME}"/.ssh/known_hosts "${HOME}"/.ssh/known_hosts
	--ro-bind-try "${HOME}"/.ssh/config "${HOME}"/.ssh/config
)

if [[ ${PWD} == "${HOME}" ]]; then
	BWRAP_ARGS+=( --chdir "${HOME}" )
else
	BWRAP_ARGS+=(
		--bind "${PWD}" "${PWD}"
		--chdir "${PWD}"
	)
fi

# Wayland display socket
if [[ -n ${WAYLAND_DISPLAY:-} && -e ${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY} ]]; then
	BWRAP_ARGS+=( --ro-bind "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" "${XDG_RUNTIME_DIR}/${WAYLAND_DISPLAY}" )
fi

# Audio server sockets (PipeWire / PulseAudio)
if [[ -S ${XDG_RUNTIME_DIR}/pipewire-0 ]]; then
	BWRAP_ARGS+=( --ro-bind "${XDG_RUNTIME_DIR}/pipewire-0" "${XDG_RUNTIME_DIR}/pipewire-0" )
fi
if [[ -d ${XDG_RUNTIME_DIR}/pulse ]]; then
	BWRAP_ARGS+=( --ro-bind "${XDG_RUNTIME_DIR}/pulse" "${XDG_RUNTIME_DIR}/pulse" )
fi

# Unity Auth Broker sockets (system-wide and per-user)
if [[ -S /run/unity-auth-broker/socket ]]; then
	BWRAP_ARGS+=( --bind /run/unity-auth-broker/socket /run/unity-auth-broker/socket )
fi

if [[ -S ${XDG_RUNTIME_DIR}/unity/auth-broker.sock ]]; then
	BWRAP_ARGS+=( --bind "${XDG_RUNTIME_DIR}/unity/auth-broker.sock" "${XDG_RUNTIME_DIR}/unity/auth-broker.sock" )
fi

# Secret Service / D-Bus session
if [[ -n ${DBUS_SESSION_BUS_ADDRESS:-} ]]; then
	case "${DBUS_SESSION_BUS_ADDRESS}" in
		unix:path=*)
			dbus_sock=${DBUS_SESSION_BUS_ADDRESS#unix:path=}
			dbus_sock=${dbus_sock%%,*}
			[[ -S ${dbus_sock} ]] && BWRAP_ARGS+=( --bind "${dbus_sock}" "${dbus_sock}" )
			;;
	esac
elif [[ -S ${XDG_RUNTIME_DIR}/bus ]]; then
	BWRAP_ARGS+=( --bind "${XDG_RUNTIME_DIR}/bus" "${XDG_RUNTIME_DIR}/bus" )
fi

# System D-Bus socket (for logind sleep inhibition before suspend)
if [[ -S /run/dbus/system_bus_socket ]]; then
	BWRAP_ARGS+=( --ro-bind /run/dbus/system_bus_socket /run/dbus/system_bus_socket )
fi

# SSH agent forwarding
if [[ -n ${SSH_AUTH_SOCK:-} && -S ${SSH_AUTH_SOCK} ]]; then
	BWRAP_ARGS+=( --bind "${SSH_AUTH_SOCK}" "${SSH_AUTH_SOCK}" )
fi

# Pass through CLI argument paths if they point to paths outside PWD and HOME
for arg in "$@"; do
	if [[ -e ${arg} ]]; then
		real_path=$(realpath "${arg}" 2>/dev/null || true)
		if [[ -n ${real_path} && ${real_path} != "${HOME}" && -e ${real_path} ]]; then
			BWRAP_ARGS+=( --bind-try "${real_path}" "${real_path}" )
		fi
	fi
done

exec bwrap "${BWRAP_ARGS[@]}" -- "@EXEC@" --no-sandbox "$@"
