#!/bin/bash
# Launch ALT Chromium through ANGLE on the isolated MCom03 PVR Xorg runtime.
set -euo pipefail

ROOT=${PVR_XORG_ROOT:-/opt/mcom03-pvr-xorg}
DISPLAY_NUM=${DISPLAY:-:1}
BROWSER=${PVR_CHROMIUM_BROWSER:-}
ALLOW_SOFTWARE=0
GPU_SANDBOX=enabled
GPU_RASTERIZATION=${PVR_CHROMIUM_GPU_RASTERIZATION:-disabled}
MVE_VIDEO_DECODING=${PVR_CHROMIUM_MVE_VIDEO_DECODING:-auto}
MVE_FRAME_HANDOFF=${PVR_CHROMIUM_MVE_FRAME_HANDOFF:-mapped-dmabuf}
STARTUP_WARMUP_SECONDS=${PVR_CHROMIUM_STARTUP_WARMUP_SECONDS:-4}
STARTUP_WARMUP=enabled
STATE_ROOT=${PVR_CHROMIUM_STATE_ROOT:-${XDG_STATE_HOME:-$HOME/.local/state}/mcom03-pvr-chromium}
PROFILE=${PVR_CHROMIUM_PROFILE:-$STATE_ROOT/profile}

usage() {
    cat <<'EOF'
Usage: pvr-chromium [launcher options] [--] [CHROMIUM_ARGUMENT ...]

Launcher options:
  --browser COMMAND   Chromium executable (default: auto-detect).
  --display :N        Vendor Xorg display (default: inherited DISPLAY or :1).
  --profile DIR       Chromium profile (default: a private per-user profile).
  --allow-software    Permit Chromium's software GL fallback.
  --diagnostic-disable-gpu-sandbox
                      Disable the GPU sandbox for fault isolation only.
  --diagnostic-disable-gpu-rasterization
                      Paint browser UI on the CPU while keeping ANGLE/WebGL.
  --diagnostic-enable-gpu-rasterization
                      Re-enable GPU-painted browser UI for A/B diagnostics.
  --diagnostic-disable-mve-video
                      Disable the MCom03 MVE hardware video decoder.
  --diagnostic-mve-cpu-frames
                      Use client-owned CPU buffers instead of mapped DMA-BUF.
  --startup-warmup-seconds N
                      Delay the first page until the PVR GPU process is ready
                      (default: 4 seconds).
  --diagnostic-no-startup-warmup
                      Open the first page during Chromium startup. This can
                      lose the initial WebGL context on the legacy PVR stack.
  -h, --help          Show this help.

Examples:
  pvr-chromium
  pvr-chromium --display :1 https://get.webgl.org/
  pvr-chromium -- --kiosk file:///home/altuser/application/index.html
EOF
}

while [ "$#" -gt 0 ]; do
    case "$1" in
        --browser)
            shift
            [ "$#" -gt 0 ] || { echo "--browser needs a value" >&2; exit 64; }
            BROWSER=$1
            shift
            ;;
        --display)
            shift
            [ "$#" -gt 0 ] || { echo "--display needs a value" >&2; exit 64; }
            DISPLAY_NUM=$1
            shift
            ;;
        --profile)
            shift
            [ "$#" -gt 0 ] || { echo "--profile needs a value" >&2; exit 64; }
            PROFILE=$1
            shift
            ;;
        --allow-software)
            ALLOW_SOFTWARE=1
            shift
            ;;
        --diagnostic-disable-gpu-sandbox)
            GPU_SANDBOX=disabled
            shift
            ;;
        --diagnostic-disable-gpu-rasterization)
            GPU_RASTERIZATION=disabled
            shift
            ;;
        --diagnostic-enable-gpu-rasterization)
            GPU_RASTERIZATION=enabled
            shift
            ;;
        --diagnostic-disable-mve-video)
            MVE_VIDEO_DECODING=disabled
            shift
            ;;
        --diagnostic-mve-cpu-frames)
            MVE_FRAME_HANDOFF=cpu
            shift
            ;;
        --startup-warmup-seconds)
            shift
            [ "$#" -gt 0 ] || { echo "--startup-warmup-seconds needs a value" >&2; exit 64; }
            STARTUP_WARMUP_SECONDS=$1
            shift
            ;;
        --diagnostic-no-startup-warmup)
            STARTUP_WARMUP=disabled
            shift
            ;;
        --)
            shift
            break
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            break
            ;;
    esac
done

USER_ARGS=("$@")

case "$GPU_RASTERIZATION" in
    enabled|disabled) ;;
    *)
        echo "PVR_CHROMIUM_GPU_RASTERIZATION must be enabled or disabled." >&2
        exit 64
        ;;
esac

case "$MVE_VIDEO_DECODING" in
    auto|enabled|disabled) ;;
    *)
        echo "PVR_CHROMIUM_MVE_VIDEO_DECODING must be auto, enabled, or disabled." >&2
        exit 64
        ;;
esac

case "$MVE_FRAME_HANDOFF" in
    mapped-dmabuf|cpu) ;;
    *)
        echo "PVR_CHROMIUM_MVE_FRAME_HANDOFF must be mapped-dmabuf or cpu." >&2
        exit 64
        ;;
esac

case "$STARTUP_WARMUP_SECONDS" in
    ""|*[!0-9]*)
        echo "--startup-warmup-seconds must be an integer from 0 to 30." >&2
        exit 64
        ;;
esac
if (( STARTUP_WARMUP_SECONDS < 0 || STARTUP_WARMUP_SECONDS > 30 )); then
    echo "--startup-warmup-seconds must be an integer from 0 to 30." >&2
    exit 64
fi

case "$DISPLAY_NUM" in
    :*) DISPLAY_ID=${DISPLAY_NUM#:}; DISPLAY_ID=${DISPLAY_ID%%.*} ;;
    *) echo "--display must have the form :N." >&2; exit 64 ;;
esac
case "$DISPLAY_ID" in
    ""|*[!0-9]*) echo "--display must have the form :N." >&2; exit 64 ;;
esac

if [ -z "$BROWSER" ]; then
    # Bypass both the desktop-facing MCom03 wrapper and ALT's shell launcher.
    # The latter injects its own --use-angle=gl and video feature flags before
    # this launcher's verified gles-egl arguments.
    if [ -x /usr/lib64/chromium/chromium ]; then
        BROWSER=/usr/lib64/chromium/chromium
    elif [ -x /usr/bin/chromium ]; then
        BROWSER=/usr/bin/chromium
    else
        for candidate in chromium-browser chromium-gost chromium; do
            if command -v "$candidate" >/dev/null 2>&1; then
                BROWSER=$(command -v "$candidate")
                break
            fi
        done
    fi
elif command -v "$BROWSER" >/dev/null 2>&1; then
    BROWSER=$(command -v "$BROWSER")
fi
[ -n "$BROWSER" ] && [ -x "$BROWSER" ] || {
    echo "No Chromium-family browser was found." >&2
    exit 1
}
[ -S "/tmp/.X11-unix/X$DISPLAY_ID" ] || {
    echo "X11 display $DISPLAY_NUM is absent." >&2
    exit 1
}
for path in \
        "$ROOT/browser/compat/lib/libEGL.so.1" \
        "$ROOT/browser/vendor/lib/libpvr_dri_support.so" \
        "$ROOT/browser/vendor/lib/pvrGLESv2.so" \
        "$ROOT/usr/local/lib/dri/pvr_dri.so"; do
    [ -e "$path" ] || { echo "Required PVR browser file is absent: $path" >&2; exit 1; }
done
if [ "$MVE_VIDEO_DECODING" = auto ]; then
    if [ -r /opt/mcom03-mve-gst/lib/libmveomx.so.0.1 ] && \
            [ -r /dev/mv500 ] && [ -w /dev/mv500 ]; then
        MVE_VIDEO_DECODING=enabled
    else
        MVE_VIDEO_DECODING=disabled
    fi
fi
if [ "$MVE_VIDEO_DECODING" = enabled ]; then
    [ -r /opt/mcom03-mve-gst/lib/libmveomx.so.0.1 ] || {
        echo "Required MVE OpenMAX library is absent." >&2
        exit 1
    }
    [ -r /dev/mv500 ] && [ -w /dev/mv500 ] || {
        echo "The current user cannot access /dev/mv500." >&2
        exit 1
    }
fi

case "$PROFILE" in
    /*) ;;
    *) echo "--profile must be an absolute path." >&2; exit 64 ;;
esac
XDG_CONFIG_HOME="$STATE_ROOT/config"
XDG_CACHE_HOME="$STATE_ROOT/cache"
umask 077
mkdir -p "$PROFILE" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME"
for path in "$PROFILE" "$XDG_CONFIG_HOME" "$XDG_CACHE_HOME"; do
    [ -w "$path" ] || {
        echo "Chromium runtime directory is not writable: $path" >&2
        exit 1
    }
done

export DISPLAY="$DISPLAY_NUM"
export XDG_CONFIG_HOME XDG_CACHE_HOME
export LD_LIBRARY_PATH="$ROOT/browser/vendor/lib:$ROOT/browser/compat/lib"
export LIBGL_DRIVERS_PATH="$ROOT/usr/local/lib/dri"
export MESA_LOADER_DRIVER_OVERRIDE=pvr
export EGL_PLATFORM=x11
unset LIBGL_ALWAYS_SOFTWARE

SANDBOX_ARG=
if [ "$GPU_SANDBOX" = enabled ]; then
    if command -v rpm >/dev/null 2>&1; then
        CHROMIUM_PACKAGE=$(rpm -q chromium 2>/dev/null || true)
        case "$CHROMIUM_PACKAGE" in
            *mcom03*) ;;
            *)
                PAYLOAD_MANIFEST=/opt/mcom03-demo/chromium-overlay-packages.txt
                PAYLOAD_INFO=/opt/mcom03-demo/chromium-overlay-info.txt
                PAYLOAD_PACKAGE=$(grep -m1 '^chromium-.*mcom03' \
                    "$PAYLOAD_MANIFEST" 2>/dev/null || true)
                PAYLOAD_SHA256=$(sed -n 's/^chromium_sha256=//p' \
                    "$PAYLOAD_INFO" 2>/dev/null)
                ACTUAL_SHA256=$(sha256sum "$BROWSER" 2>/dev/null | \
                    awk '{print $1}')
                if [ -n "$PAYLOAD_PACKAGE" ] && [ -n "$PAYLOAD_SHA256" ] && \
                        [ "$PAYLOAD_SHA256" = "$ACTUAL_SHA256" ] && \
                        grep -q '^intended_use=experimental_PoC_rootfs_only$' \
                            "$PAYLOAD_INFO" && \
                        grep -q '^gpu_sandbox=seccomp_tsync_required$' \
                            "$PAYLOAD_INFO"; then
                    echo "WARNING: using the MCom03 TSYNC payload manifest without RPM registration." >&2
                else
                    echo "Sandboxed PVR Chromium requires the MCom03 TSYNC Chromium package." >&2
                    echo "Installed package: ${CHROMIUM_PACKAGE:-not-found}" >&2
                    exit 1
                fi
                ;;
        esac
    fi
else
    SANDBOX_ARG=--disable-gpu-sandbox
    echo "WARNING: Chromium GPU sandbox is disabled for diagnostics." >&2
fi

CHROMIUM_ARGS=(
    "$BROWSER"
    --ignore-gpu-blocklist
    --ozone-platform=x11
    --use-gl=angle
    --use-angle=gles-egl
    --mcom03-pvr-x11-root-visual
    --user-data-dir="$PROFILE"
    --disable-breakpad
    --disable-crash-reporter
    --no-first-run
    --no-default-browser-check
    "--window-size=1280,900"
)
if [ "$MVE_VIDEO_DECODING" = enabled ]; then
    MVE_FEATURES=MCom03MveVideoDecoder
    if [ "$MVE_FRAME_HANDOFF" = mapped-dmabuf ]; then
        MVE_FEATURES=$MVE_FEATURES,MCom03MveMappedDmaBufVideoFrames
    fi
    CHROMIUM_ARGS+=("--enable-features=$MVE_FEATURES")
fi
if [ "$GPU_RASTERIZATION" = enabled ]; then
    CHROMIUM_ARGS+=(--enable-gpu-rasterization)
else
    CHROMIUM_ARGS+=(--disable-gpu-rasterization)
fi
if [ -n "$SANDBOX_ARG" ]; then
    CHROMIUM_ARGS+=("$SANDBOX_ARG")
fi
if [ "$ALLOW_SOFTWARE" -eq 0 ]; then
    CHROMIUM_ARGS+=(--disable-software-rasterizer)
fi

profile_browser_running() {
    local proc cmdline
    for proc in /proc/[0-9]*; do
        [ -r "$proc/cmdline" ] || continue
        cmdline=$(tr '\0' ' ' <"$proc/cmdline" 2>/dev/null) || continue
        case "$cmdline" in
            *"--user-data-dir=$PROFILE"*) return 0 ;;
        esac
    done
    return 1
}

if [ "$STARTUP_WARMUP" = disabled ] || profile_browser_running; then
    exec "${CHROMIUM_ARGS[@]}" "${USER_ARGS[@]}"
fi

TARGET=
APP_MODE=0
BROWSER_USER_ARGS=()
for argument in "${USER_ARGS[@]}"; do
    case "$argument" in
        --app=*)
            [ -z "$TARGET" ] || {
                echo "Only one initial Chromium target is supported during PVR warm-up." >&2
                exit 64
            }
            TARGET=${argument#--app=}
            APP_MODE=1
            ;;
        --kiosk=*)
            [ -z "$TARGET" ] || {
                echo "Only one initial Chromium target is supported during PVR warm-up." >&2
                exit 64
            }
            TARGET=${argument#--kiosk=}
            BROWSER_USER_ARGS+=(--kiosk)
            ;;
        -*)
            BROWSER_USER_ARGS+=("$argument")
            ;;
        *)
            [ -z "$TARGET" ] || {
                echo "Only one initial Chromium target is supported during PVR warm-up." >&2
                exit 64
            }
            TARGET=$argument
            ;;
    esac
done

if [ -z "$TARGET" ]; then
    TARGET=about:blank
elif [[ "$TARGET" = /* ]] && [ -e "$TARGET" ]; then
    TARGET="file://$(readlink -f "$TARGET")"
fi

WARMUP_PAGE="$ROOT/mcom03-chromium-warmup.html"
[ -r "$WARMUP_PAGE" ] || {
    echo "Chromium PVR warm-up page is absent: $WARMUP_PAGE" >&2
    exit 1
}
ENCODED_TARGET=$(printf '%s' "$TARGET" | base64 | tr -d '\n' | tr '+/' '-_' | tr -d '=')
WARMUP_URL="file://$WARMUP_PAGE?delay=$((STARTUP_WARMUP_SECONDS * 1000))&target=$ENCODED_TARGET"

if [ "$APP_MODE" -eq 1 ]; then
    BROWSER_USER_ARGS+=("--app=$WARMUP_URL")
    exec "${CHROMIUM_ARGS[@]}" "${BROWSER_USER_ARGS[@]}"
fi
exec "${CHROMIUM_ARGS[@]}" "${BROWSER_USER_ARGS[@]}" "$WARMUP_URL"
