#!/bin/sh

BASE="/mnt/onboard/.adds/kobo-sideload-sync"
FBINK="$BASE/third-party/fbink/bin/fbink"
FBINK_LIB_DIR="$BASE/third-party/fbink/lib"
ACK_IMAGE="$BASE/assets/finish-acknowledgement.png"
DIAGNOSTIC_LOG="$BASE/run/finish-feedback.log"
DIAGNOSTIC_TMP="$BASE/run/.finish-feedback.log.tmp"
MAX_WAIT_TENTHS=15
WAIT_TENTHS="${KSS_FINISH_ACK_WAIT_TENTHS:-$MAX_WAIT_TENTHS}"

if [ -r "$BASE/action-timing.sh" ]; then
    . "$BASE/action-timing.sh"
else
    kss_timing_event() { :; }
fi

kss_timing_event finish_feedback_begin

if [ -f "$BASE/universal-candidate.txt" ]; then
    /bin/sh "$BASE/device-preflight.sh" --basic >/dev/null 2>&1 || exit 0
    if "$BASE/bin/kobo-receiver" --device-ack=finish >/dev/null 2>&1; then
        kss_timing_event finish_feedback_ok
    else
        kss_timing_event finish_feedback_fail
    fi
    exit 0
fi

record_feedback_failure() {
    failure_reason="$1"
    failure_exit_code="$2"
    case "$failure_reason" in
        preflight_fbink|preflight_library|preflight_image|fbink_exit|timeout) ;;
        *) failure_reason="unknown" ;;
    esac
    case "$failure_exit_code" in
        ''|*[!0-9]*) failure_exit_code="na" ;;
    esac
    umask 077
    mkdir -p "$BASE/run" 2>/dev/null || return 0
    if printf 'v1 reason=%s exit_code=%s\n' "$failure_reason" "$failure_exit_code" > "$DIAGNOSTIC_TMP" 2>/dev/null; then
        mv -f "$DIAGNOSTIC_TMP" "$DIAGNOSTIC_LOG" 2>/dev/null || :
    fi
    rm -f "$DIAGNOSTIC_TMP" 2>/dev/null || :
}

clear_feedback_failure() {
    rm -f "$DIAGNOSTIC_TMP" "$DIAGNOSTIC_LOG" 2>/dev/null || :
}

clear_feedback_failure

# Feedback must never become a new safety gate. A corrupt or incomplete install
# may lose this acknowledgement, but the existing fail-closed finish checks must
# still run and retain their own visible rejection/recovery messages.
if [ ! -x "$FBINK" ]; then
    record_feedback_failure preflight_fbink 126
    kss_timing_event finish_feedback_fail
    exit 0
fi
if [ ! -r "$FBINK_LIB_DIR/libfbink.so.1" ]; then
    record_feedback_failure preflight_library 126
    kss_timing_event finish_feedback_fail
    exit 0
fi
if [ ! -s "$ACK_IMAGE" ]; then
    record_feedback_failure preflight_image 66
    kss_timing_event finish_feedback_fail
    exit 0
fi

case "$WAIT_TENTHS" in
    ''|*[!0-9]*) WAIT_TENTHS="$MAX_WAIT_TENTHS" ;;
esac
if [ "$WAIT_TENTHS" -lt 1 ]; then
    WAIT_TENTHS=1
elif [ "$WAIT_TENTHS" -gt "$MAX_WAIT_TENTHS" ]; then
    WAIT_TENTHS="$MAX_WAIT_TENTHS"
fi

# FBInk is private to this project. The image contains the Chinese glyphs, so
# rendering does not depend on Kobo's obfuscated system fonts. Flash only the
# image rectangle, wait for the e-ink submission to complete, and show no modal
# control or OK button.
LD_LIBRARY_PATH="$FBINK_LIB_DIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH
"$FBINK" -q -f -w -i "$ACK_IMAGE" -g halign=CENTER,valign=CENTER >/dev/null 2>&1 &
fbink_pid=$!

attempt=0
while kill -0 "$fbink_pid" 2>/dev/null && [ "$attempt" -lt "$WAIT_TENTHS" ]; do
    attempt=$((attempt + 1))
    sleep 0.1
done

if kill -0 "$fbink_pid" 2>/dev/null; then
    # Do not let a stuck framebuffer wait delay or cancel the finish request.
    kill "$fbink_pid" 2>/dev/null || :
    sleep 0.1
    kill -9 "$fbink_pid" 2>/dev/null || :
    wait "$fbink_pid" 2>/dev/null || :
    record_feedback_failure timeout 124
    kss_timing_event finish_feedback_timeout
else
    wait "$fbink_pid" 2>/dev/null
    fbink_result=$?
    if [ "$fbink_result" -eq 0 ]; then
        kss_timing_event finish_feedback_ok
    else
        record_feedback_failure fbink_exit "$fbink_result"
        kss_timing_event finish_feedback_fail
    fi
fi

exit 0
