#!/usr/sbin/openrc-run

set -e

description="KMS fallback and background coldplug (early seed, promote, sysfs sweep)"

depend()
{
	after mountkernfs.sh
	before mountdevsubfs.sh
	provide vdev-coldplug
	keyword -containers
}

: "${VDEV_BIN:=/sbin/vdevd}"
[ -x "${VDEV_BIN}" ] || exit 0

: "${VDEV_MOUNTPOINT:=/dev}"
: "${VDEV_UDEV_CONTROL:=/run/udev/control}"

_json="${VDEV_GLOBALS_JSON:-/etc/vdev/vdevd.globals.json}"

if [ -r "${_json}" ] && command -v jq >/dev/null 2>&1; then
	VDEV_JSON_DATA="$(sed -E 's|//.*||g' "${_json}" |
		sed 's|/\*.*\*/||g' |
		grep -v '^$' |
		jq -r .)"
	export VDEV_JSON_DATA
else
	VDEV_CONFIG_DIR="/etc/vdev"
	VDEV_TERMINAL="vdevd.1.conf"
	VDEV_LONG_RUNNING="vdevd.conf"
	VDEV_STAMP_DIR="/run/vdev"
	VDEV_READY_STAMP="/run/vdev/vdev.ready"
	VDEV_EARLY_SUBSYSTEMS="graphics video4linux input hid i2c drm fd"
fi

get_json_get_key() {
	printf '%s' "${VDEV_JSON_DATA}" | jq -r --arg k "$1" '
		.globals[$k] // empty'
}

get_json_get_config() {
	printf '%s' "${VDEV_JSON_DATA}" | jq -r --arg s "$1" '
		.profiles[$s].config // .states[$s].config // empty'
}

get_json_get_stamp() {
	printf '%s' "${VDEV_JSON_DATA}" | jq -r --arg s "$1" '
		.profiles[$s].stamp // .states[$s].stamp // empty'
}

get_json_get_subsystems() {
	printf '%s' "${VDEV_JSON_DATA}" | jq -r --arg s "$1" '
		(.profiles[$s].subsystems // .states[$s].subsystems // []) | .[]'
}

if [ -n "${VDEV_JSON_DATA}" ]; then
	_config_dir="$(get_json_get_key "config-dir")"
	VDEV_CONFIG_DIR="${_config_dir:-/etc/vdev}"

	_TERMINAL="$(get_json_get_config "terminal")"
	VDEV_TERMINAL="${_terminal:-vdevd.1.conf}"

	_long_running="$(get_json_get_config "long-running")"
	VDEV_LONG_RUNNING="${_long_running:-vdevd.conf}"

	_stamp_dir="$(get_json_get_key "states-stamp-dir")"
	VDEV_STAMP_DIR="${_stamp_dir:-/run/vdev}"

	_stamp_early="$(get_json_get_stamp "early")"
	VDEV_READY_STAMP="${VDEV_STAMP_DIR}/${_stamp_early:-vdev.ready}"

	_early_subs="$(get_json_get_subsystems "early" | tr '\n' ' ')"
	VDEV_EARLY_SUBSYSTEMS="${_early_subs:-graphics video4linux input hid i2c drm fd}"
fi

VDEV_TERMINAL_CONFIG="${VDEV_CONFIG_DIR}/${VDEV_TERMINAL}"
VDEV_LONG_RUNNING_CONFIG="${VDEV_CONFIG_DIR}/${VDEV_LONG_RUNNING}"

vdev_wait_for_stamp() {
	local _vs_path="$1" _vs_max="${2:-250}" _vs_sleep="${3:-0.2}" _vs_i=0

	while [ "${_vs_i}" -lt "${_vs_max}" ]; do
		[ -e "${_vs_path}" ] && return 0
		sleep "${_vs_sleep}"
		_vs_i=$((_vs_i + 1))
	done
	return 1
}

load_boot_vga_kms()
{
	local boot_file pci_dir alias_string

	for boot_file in /sys/bus/pci/devices/*/boot_vga; do
		[ -f "${boot_file}" ] || continue
		[ "$(cat "${boot_file}")" = "1" ] || continue
		pci_dir=$(dirname "${boot_file}")
		[ -f "${pci_dir}/modalias" ] || continue
		alias_string=$(cat "${pci_dir}/modalias")
		case "${alias_string}" in
			*v00008086*|*v000010DE*)
				# Intel / NVIDIA: load from modalias (i915 / nouveau).
				modprobe -q "${alias_string}" 2>/dev/null || true
				;;
			*v00001002*)
				# AMD: skip amdgpu here — can load after X; often noisy /
				# slow when proprietary firmware is missing. Initrd only.
				;;
			*)
				[ -n "${alias_string}" ] && modprobe -q nouveau 2>/dev/null || true
				;;
		esac
		break
	done
}

vdev_promote_to_long_running() {
	local _try=0 _max="${VDEV_PROMOTE_RETRIES:-5}"
	local _cfg="${VDEV_LONG_RUNNING_CONFIG:-}"

	while [ "${_try}" -lt "${_max}" ]; do
		_try=$((_try + 1))
		if [ -n "${_cfg}" ]; then
			vdevadm control --promote="${_cfg}" >/dev/null 2>&1 && return 0
		else
			vdevadm control --promote >/dev/null 2>&1 && return 0
		fi
		sleep 0.1
	done
	return 1
}

# Background worker: wait for vdev early control, seed actions.early, settle,
# promote to long-running, then full sysfs trigger (post-promote; not waited).
vdev_coldplug_worker() {
	local _s
	local _cfg="${VDEV_TERMINAL_CONFIG:-}"

	vdev_wait_for_stamp "${VDEV_UDEV_CONTROL}" 250 0.1 || return 0

	for _s in ${VDEV_EARLY_SUBSYSTEMS}; do
		vdevadm trigger -s "${_s}" -a add >/dev/null 2>&1 || true
	done
	vdevadm settle -t "${VDEV_EARLY_SETTLE_TIMEOUT:-15}" >/dev/null 2>&1 || true

	vdev_promote_to_long_running || true

	#vdevadm trigger --sysfs -a add >/dev/null 2>&1 || true
    "${VDEV_BIN}" -1 -c "${VDEV_TERMINAL_CONFIG}" "${VDEV_MOUNTPOINT}"
}

start()
{
	# KMS fallback only; failures must not block vdev (separate service).
	load_boot_vga_kms

	einfo "Starting coldplug worker in background"
	( vdev_coldplug_worker ) >/dev/null 2>&1 &
}

stop()
{
	:
}
