#!/bin/sh
set -eu

MODE="${1:-}"
MODULES="cam-epc670 clk-si5351"
SHAREDIR="/usr/share/epc"
STATEDIR="/var/lib/epc670"
STAMP_FILE="${STATEDIR}/firstboot.done"
SPI_FLASH_MISSING=0
EPC670_MISSING=0

log() {
    echo "epc670 finalize: $*"
}

fail() {
    log "ERROR: $*"
    exit 1
}

read_ver() {
    mod="$1"
    f="${SHAREDIR}/${mod}.version"
    if [ -r "$f" ]; then
        tr -d ' \t\r\n' < "$f"
    fi
}

need_live_system() {
    [ -d /run/systemd/system ] || fail "systemd is not running"
    command -v uname >/dev/null 2>&1 || fail "uname not available"
    KVER="$(uname -r)"
    [ -n "$KVER" ] || fail "running kernel version unavailable"
    log "Running kernel version: ${KVER}"
    [ -d "/lib/modules/$KVER" ] || fail "missing /lib/modules/$KVER"
    log "Kernel module tree found for ${KVER}"
}

check_dkms_source() {
    mod="$1"
    ver="$2"
    if ! dkms status -m "$mod" -v "$ver" 2>/dev/null | grep -q "^${mod}/${ver}"; then
        fail "DKMS source for ${mod}/${ver} is missing (expected to be registered by epc-drivers-dkms postinst). The epc-drivers-dkms installation appears to be broken; please reinstall the epc-drivers-dkms package."
    fi
}

check_installed_one() {
    mod="$1"
    ver="$2"
    [ -n "$ver" ] || fail "missing version for ${mod} (expected ${SHAREDIR}/${mod}.version). The epc-drivers-dkms installation appears to be broken; please reinstall the epc-drivers-dkms package."
    check_dkms_source "$mod" "$ver"

    if dkms status -m "$mod" -v "$ver" 2>/dev/null | grep -q "installed"; then
        log "Module ${mod}/${ver} is already installed for kernel ${KVER}, skipping"
    else
        log "Module ${mod}/${ver} not yet installed; running dkms install"
        dkms install -m "$mod" -v "$ver" || fail "dkms install failed for ${mod}/${ver}"
    fi
}

start_runtime_bits() {
    if command -v depmod >/dev/null 2>&1; then
        log "Running depmod -a"
        depmod -a || log "Warning: depmod failed"
    fi

    if command -v modprobe >/dev/null 2>&1; then
        # Reverse order so dependencies (e.g. clk-si5351) load before cam-epc670
        for mod in $(printf '%s\n' $MODULES | sort -r); do
            log "Trying modprobe ${mod}"
            modprobe "$mod" || log "Warning: modprobe ${mod} failed"
        done
    fi

    if command -v systemd-tmpfiles >/dev/null 2>&1; then
        log "Creating tmpfiles entries"
        systemd-tmpfiles --create /usr/lib/tmpfiles.d/epc670-tofhat-tmpfiles.conf || \
            log "Warning: systemd-tmpfiles failed"
    fi

    if command -v udevadm >/dev/null 2>&1; then
        log "Reloading udev rules"
        udevadm control --reload-rules || log "Warning: udevadm control failed"
        log "Triggering video4linux udev events"
        udevadm trigger --subsystem-match=video4linux || log "Warning: udevadm trigger failed"
        log "Settling udev events"
        udevadm settle || log "Warning: udevadm settle failed"
    fi

    if command -v systemctl >/dev/null 2>&1; then
        log "Starting mnt-spi_flash.automount"
        systemctl start mnt-spi_flash.automount || \
            log "Warning: failed to start mnt-spi_flash.automount"

        log "Checking for SPI flash device"
        if [ -e /dev/mtdblock0 ]; then
            log "Device found, starting epctofcam-spi_flash-sync.service"
            systemctl start epctofcam-spi_flash-sync.service || \
                log "Warning: failed to start epctofcam-spi_flash-sync.service"
        else
            log "Device not found, enabling epctofcam-spi_flash-sync.service for later"
            systemctl enable epctofcam-spi_flash-sync.service || \
                log "Warning: failed to enable epctofcam-spi_flash-sync.service"
            SPI_FLASH_MISSING=1
        fi

        log "Checking for epc670 subdev"
        if [ -e /dev/epc670_subdev ]; then
            log "epc670 device found, starting dependent services"
            systemctl start epc670-tofhat-gpio-boot.service || \
                log "Warning: failed to start epc670-tofhat-gpio-boot.service! Reboot is needed"
            systemctl start epc670-tofhat-nodes.service || \
                log "Warning: failed to start epc670-tofhat-nodes.service! Reboot is needed"
            systemctl start epc670-tofhat-config.service || \
                log "Warning: failed to start epc670-tofhat-config.service! Reboot is needed"
        else
            log "Device not found, enabling dependent services for later"
            systemctl enable epc670-tofhat-gpio-boot.service || \
                log "Warning: failed to enable epc670-tofhat-gpio-boot.service"
            systemctl enable epc670-tofhat-nodes.service || \
                log "Warning: failed to enable epc670-tofhat-nodes.service"
            systemctl enable epc670-tofhat-config.service || \
                log "Warning: failed to enable epc670-tofhat-config.service"
            EPC670_MISSING=1
        fi
    fi
}

case "$MODE" in
    --now|--firstboot)
        ;;
    *)
        fail "usage: $0 --now|--firstboot"
        ;;
esac

log "Starting finalize in mode ${MODE}"
log "Using SHAREDIR=${SHAREDIR}"
log "Using STATEDIR=${STATEDIR}"

need_live_system

command -v dkms >/dev/null 2>&1 || fail "dkms not installed"
log "dkms found: $(command -v dkms)"

for mod in $MODULES; do
    ver="$(read_ver "$mod" || true)"
    log "Resolved ${mod} version: ${ver:-<missing>}"
    check_installed_one "$mod" "$ver"
done

start_runtime_bits

if [ "$MODE" = "--firstboot" ]; then
    mkdir -p "$STATEDIR"
    touch "$STAMP_FILE"
    log "Created first-boot stamp ${STAMP_FILE}"
fi

if [ "$EPC670_MISSING" = "1" ] && [ "$SPI_FLASH_MISSING" = "1" ]; then
    log " "
    log "=========================================="
    log "WARNING: epc670 device was not detected."
    log "WARNING: The device is either not connected"
    log "WARNING: OR this is the first ever installation."
    log "WARNING: Please shut down, connect the epc670 tofhat"
    log "WARNING: (if not already connected)"
    log "WARNING: and boot again. All services will"
    log "WARNING: start automatically on next boot."
    log "=========================================="
    log " "
elif [ "$SPI_FLASH_MISSING" = "1" ]; then
    log " "
    log "=========================================="
    log "WARNING: SPI flash device was not detected."
    log "WARNING: The epc670 appears to be connected but"
    log "WARNING: there may be a problem with the SPI flash."
    log "WARNING: Check the SPI flash connection and"
    log "WARNING: configuration, then reboot to retry."
    log "=========================================="
    log " "
fi

log "Finalize completed successfully"
exit 0
