#!/bin/sh
# Copyright (C) 2026 Aitor <aitor@genuen.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

set -e

is_openrc() {
	# True when OpenRC has entered a runlevel (live system / after boot).
	[ -f /run/openrc/softlevel ]
}

have_rc_tools() {
	command -v rc-update >/dev/null 2>&1
}

have_rc_service() {
	command -v rc-service >/dev/null 2>&1
}

run_or_error() {
	if ! "$@"; then
		eval "${ERROR_HANDLER:-exit 1}"
	fi
}

scrub_runlevels() {
	local _dh_rl

	# Prefer rc-update when OpenRC is live; always scrub symlinks by hand so
	# chroot/image builds (no softlevel) still get a clean slate before add.
	if is_openrc && have_rc_tools; then
		for _dh_rl in boot default sysinit recovery off shutdown nonetwork; do
			rc-update -q del "$SCRIPT" "$_dh_rl" 2>/dev/null || true
		done
	fi
	for _dh_rl in /etc/runlevels/*/; do
		rm -f "${_dh_rl}${SCRIPT}" 2>/dev/null || true
	done
}

configure_runlevel() {
	if [ -z "${RUNLEVEL:-}" ]; then
		return 0
	fi
	# Register into /etc/runlevels whenever OpenRC tooling is present.
	# Do NOT treat /run/runit or /run/s6 as "another init is live": dh-runit /
	# dh-s6 create those directories during postinst even when the image boots
	# with OpenRC (and runit/s6 packages are not installed). softlevel is only
	# required for start/stop, not for rc-update add.
	if [ ! -d /etc/runlevels ]; then
		return 0
	fi
	if [ ! -d "/etc/runlevels/${RUNLEVEL}" ]; then
		echo "warning: openrc-helper: runlevel ${RUNLEVEL} missing, skipping ${SCRIPT}" >&2
		return 0
	fi
	scrub_runlevels
	if have_rc_tools && rc-update add "$SCRIPT" "$RUNLEVEL" >/dev/null 2>&1; then
		return 0
	fi
	# Fallback when rc-update refuses without a live softlevel.
	ln -sfn "/etc/init.d/${SCRIPT}" "/etc/runlevels/${RUNLEVEL}/${SCRIPT}"
}

start_service() {
	if ! is_openrc || ! have_rc_service; then
		return 0
	fi
	run_or_error rc-service "$SCRIPT" start
}

stop_service() {
	if ! is_openrc || ! have_rc_service; then
		return 0
	fi
	run_or_error rc-service "$SCRIPT" stop
}

preinst_chmod() {
	local action="${1}"

	if [ "$action" = install ] && [ -n "${2:-}" ] && [ -e "/etc/init.d/${SCRIPT}" ]; then
		chmod +x "/etc/init.d/${SCRIPT}" >/dev/null || true
	fi
}

preinst_stop() {
	local action="${1}"

	if [ "$action" = upgrade ] && [ -x "/etc/init.d/${SCRIPT}" ]; then
		stop_service
	fi
}

postinst() {
	local action="${1}"

	case "$action" in
		configure|abort-upgrade|abort-deconfigure|abort-remove)
			;;
		*)
			return 0
			;;
	esac

	if [ ! -x "/etc/init.d/${SCRIPT}" ]; then
		return 0
	fi

	configure_runlevel
	start_service
}

postinst_restart() {
	local action="${1}"
	local previous="${2:-}"

	case "$action" in
		configure|abort-upgrade|abort-deconfigure|abort-remove)
			;;
		*)
			return 0
			;;
	esac

	if [ ! -x "/etc/init.d/${SCRIPT}" ]; then
		return 0
	fi

	configure_runlevel
	if ! is_openrc || ! have_rc_service; then
		return 0
	fi
	if [ -n "$previous" ]; then
		run_or_error rc-service "$SCRIPT" restart
	else
		run_or_error rc-service "$SCRIPT" start
	fi
}

postinst_nostart() {
	local action="${1}"

	case "$action" in
		configure|abort-upgrade|abort-deconfigure|abort-remove)
			;;
		*)
			return 0
			;;
	esac

	if [ ! -x "/etc/init.d/${SCRIPT}" ]; then
		return 0
	fi

	configure_runlevel
}

prerm_norestart() {
	local action="${1}"

	if [ "$action" = remove ] && [ -x "/etc/init.d/${SCRIPT}" ]; then
		stop_service
	fi
}

prerm() {
	if [ -x "/etc/init.d/${SCRIPT}" ]; then
		stop_service
	fi
}

postrm() {
	local action="${1}"

	if [ "$action" = remove ] && [ -x "/etc/init.d/${SCRIPT}" ]; then
		chmod -x "/etc/init.d/${SCRIPT}" >/dev/null || true
	fi

	if [ "$action" != purge ]; then
		return 0
	fi

	# Symlink scrub works without a live softlevel.
	scrub_runlevels
}

"$@"
