#!/usr/bin/env sh
set -u

preset="linux-clang"
configuration="Debug"
target="PanoPainter"
cmake_command="cmake"
artifact="out/build/$preset/$target"
readiness_only=0
android_native_checks=0
package_kinds="windows-appx,android-standard-apk,android-quest-apk,android-focus-apk,apple-bundle,linux-app,webgl"

while [ "$#" -gt 0 ]; do
    case "$1" in
        --readiness-only)
            readiness_only=1
            shift
            ;;
        --android-native-checks)
            android_native_checks=1
            shift
            ;;
        --package-kinds=*)
            package_kinds="${1#*=}"
            shift
            ;;
        --package-kinds)
            shift
            if [ "$#" -gt 0 ]; then
                package_kinds="$1"
                shift
            fi
            ;;
        --)
            shift
            break
            ;;
        -*)
            echo "Unknown option: $1" >&2
            exit 1
            ;;
        *)
            break
            ;;
    esac
done

if [ "$#" -ge 1 ]; then
    preset="${1:-$preset}"
    configuration="${2:-$configuration}"
    target="${3:-$target}"
    artifact="${4:-out/build/$preset/$target}"
fi

start="$(date +%s)"
root="$(pwd)"
package_kinds="$(printf "%s" "$package_kinds" | tr -d " ")"

json_escape() {
    printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\r/\\r/g; s/\n/\\n/g'
}

json_string() {
    printf '"%s"' "$(json_escape "$1")"
}

json_bool() {
    if [ "$1" -eq 1 ]; then
        printf true
    else
        printf false
    fi
}

json_array_from_csv() {
    local csv="$1"
    local first=1
    local value
    local items=""

    IFS=','
    for value in $csv; do
        if [ -z "$value" ]; then
            continue
        fi
        if [ "$first" -eq 1 ]; then
            first=0
        else
            items="${items},"
        fi
        items="${items}$(json_string "$value")"
    done
    unset IFS

    printf "[%s]" "$items"
}

command_available() {
    command -v "$1" >/dev/null 2>&1
}

file_available() {
    [ -f "$1" ]
}

dir_available() {
    [ -d "$1" ]
}

resolve_status() {
    local root_target="$1"
    local gate_blocked="$2"
    shift 2

    if [ "$gate_blocked" -ne 0 ]; then
        printf "blocked"
        return
    fi

    for prereq in "$@"; do
        if [ "$prereq" -ne 1 ]; then
            printf "blocked"
            return
        fi
    done

    if [ "$root_target" -ne 0 ]; then
        printf "validated"
    else
        printf "compile-only"
    fi
}

append_json_item() {
    if [ -z "$package_readiness" ]; then
        package_readiness="$1"
    else
        package_readiness="${package_readiness},$1"
    fi
}

append_result_item() {
    if [ -z "$android_native_results" ]; then
        android_native_results="$1"
    else
        android_native_results="${android_native_results},$1"
    fi
}

prerequisite_entry() {
    local name="$1"
    local available="$2"
    local detail="$3"

    printf '{'
    printf '"name":%s,' "$(json_string "$name")"
    printf '"available":%s,' "$(json_bool "$available")"
    printf '"detail":%s' "$(json_string "$detail")"
    printf '}'
}

artifact_entry() {
    local name="$1"
    local path="$2"
    local path_type="$3"
    local exists=0

    printf '{'
    printf '"name":%s,' "$(json_string "$name")"
    printf '"path":%s,' "$(json_string "$path")"
    printf '"pathType":%s,' "$(json_string "$path_type")"
    if [ "$path_type" = "Leaf" ]; then
        [ -f "$path" ]
        exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    elif [ "$path_type" = "Container" ]; then
        [ -d "$path" ]
        exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    else
        [ -e "$path" ]
        exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    fi
    printf '"exists":%s' "$(json_bool "$exists")"
    printf '}'
}

check_entry() {
    local name="$1"
    local path="$2"
    local exists="$3"

    printf '{'
    printf '"name":%s,' "$(json_string "$name")"
    printf '"path":%s,' "$(json_string "$path")"
    printf '"exists":%s' "$(json_bool "$exists")"
    printf '}'
}

is_kind_requested() {
    case ",${package_kinds}," in
        *,"$1",*)
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

run_android_native_check() {
    local packages="$1"
    local configure_only="$2"
    local command="powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages $packages"
    if [ "$configure_only" -ne 0 ]; then
        command="${command} -ConfigureOnly"
    fi

    if ! command_available powershell; then
        android_native_last_exit_code=127
        printf '{"packages":%s,"configureOnly":%s,"exitCode":%s,"command":%s,"summary":null}' \
            "$(json_array_from_csv "$packages")" \
            "$(json_bool "$configure_only")" \
            "$android_native_last_exit_code" \
            "$(json_string "$command")"
        return
    fi

    if [ "$configure_only" -ne 0 ]; then
        output="$(powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages "$packages" -ConfigureOnly 2>&1)"
    else
        output="$(powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages "$packages" 2>&1)"
    fi
    android_native_last_exit_code=$?

    summary="$(printf '%s\n' "$output" | awk 'BEGIN{line="";} /^\{/{line=$0} END{if (line != "") print line}')"
    if [ -z "$summary" ]; then
        summary="null"
    fi

    printf '{"packages":%s,"configureOnly":%s,"exitCode":%s,"command":%s,"summary":%s}' \
        "$(json_array_from_csv "$packages")" \
        "$(json_bool "$configure_only")" \
        "$android_native_last_exit_code" \
        "$(json_string "$command")" \
        "$summary"
}

extract_exit_code() {
    printf '%s' "$1" | awk -F '"exitCode":' 'NF == 2 { gsub(/[^0-9].*/, "", $2); print $2 }'
}

build_android_native_validation() {
    local standard_command="powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages standard"
    local qf_packages=""
    local qf_command="powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages $qf_packages -ConfigureOnly"

    local request_standard=0
    local request_qf=0

    if is_kind_requested "android-standard-apk"; then
        request_standard=1
    fi
    if is_kind_requested "android-quest-apk" || is_kind_requested "android-focus-apk"; then
        request_qf=1
        if is_kind_requested "android-quest-apk"; then
            qf_packages="quest"
        fi
        if is_kind_requested "android-focus-apk"; then
            if [ -n "$qf_packages" ]; then
                qf_packages="${qf_packages},focus"
            else
                qf_packages="focus"
            fi
        fi
        qf_command="powershell -ExecutionPolicy Bypass -File scripts/automation/android-legacy-package-build.ps1 -Packages $qf_packages -ConfigureOnly"
    fi

    android_native_standard_available=1
    android_native_quest_available=1
    android_native_focus_available=1
    android_native_standard_detail="${standard_command} (not run)"
    android_native_quest_detail="${qf_command} (not run)"
    android_native_focus_detail="${qf_command} (not run)"

    local requested="false"
    local exit_code=0
    android_native_results=""
    android_native_last_exit_code=0

    if [ "$android_native_checks" -eq 0 ]; then
        android_native_validation='{"requested":false,"exitCode":0,"results":[]}'
        return
    fi

    if [ "$request_standard" -eq 1 ]; then
        requested="true"
        standard_result="$(run_android_native_check "standard" 0)"
        append_result_item "$standard_result"
        standard_exit_code="$(extract_exit_code "$standard_result")"
        if [ -z "$standard_exit_code" ]; then
            standard_exit_code=0
        fi
        if [ "$standard_exit_code" -ne 0 ] && [ "$exit_code" -eq 0 ]; then
            exit_code="$standard_exit_code"
        fi

        if [ "$standard_exit_code" -eq 0 ]; then
            android_native_standard_available=1
            android_native_standard_detail="$standard_command"
        else
            android_native_standard_available=0
            android_native_standard_detail="${standard_command} (exit $standard_exit_code)"
        fi
    fi

    if [ "$request_qf" -eq 1 ] && [ -n "$qf_packages" ]; then
        requested="true"
        qf_result="$(run_android_native_check "$qf_packages" 1)"
        append_result_item "$qf_result"
        qf_exit_code="$(extract_exit_code "$qf_result")"
        if [ -z "$qf_exit_code" ]; then
            qf_exit_code=0
        fi
        if [ "$qf_exit_code" -ne 0 ] && [ "$exit_code" -eq 0 ]; then
            exit_code="$qf_exit_code"
        fi

        if [ "$qf_exit_code" -eq 0 ]; then
            if is_kind_requested "android-quest-apk"; then
                android_native_quest_available=1
                android_native_quest_detail="$qf_command"
            else
                android_native_quest_detail="$qf_command (not executed)"
            fi

            if is_kind_requested "android-focus-apk"; then
                android_native_focus_available=1
                android_native_focus_detail="$qf_command"
            else
                android_native_focus_detail="$qf_command (not executed)"
            fi
        else
            if is_kind_requested "android-quest-apk"; then
                android_native_quest_available=0
                android_native_quest_detail="${qf_command} (exit $qf_exit_code)"
            else
                android_native_quest_detail="$qf_command (not executed)"
            fi

            if is_kind_requested "android-focus-apk"; then
                android_native_focus_available=0
                android_native_focus_detail="${qf_command} (exit $qf_exit_code)"
            else
                android_native_focus_detail="$qf_command (not executed)"
            fi
        fi
    fi

    android_native_validation="{\"requested\":$requested,\"exitCode\":$exit_code,\"results\":[${android_native_results}]}"
}

build_package_readiness() {
    package_readiness=""

    windows_wapproj="$root/PanoPainterPackage/PanoPainterPackage.wapproj"
    windows_manifest="$root/PanoPainterPackage/Package.appxmanifest"
    windows_output="$root/PanoPainterPackage/AppPackages"

    android_standard_gradle="$root/android/android/build.gradle"
    android_standard_manifest="$root/android/android/src/main/AndroidManifest.xml"
    android_standard_output="$root/android/android/build/outputs/apk"

    android_quest_gradle="$root/android/quest/build.gradle"
    android_quest_manifest="$root/android/quest/src/main/AndroidManifest.xml"
    android_quest_output="$root/android/quest/build/outputs/apk"

    android_focus_gradle="$root/android/focus/build.gradle"
    android_focus_manifest="$root/android/focus/src/main/AndroidManifest.xml"
    android_focus_output="$root/android/focus/build/outputs/apk"

    apple_project="$root/PanoPainter.xcodeproj/project.pbxproj"
    apple_output="$root/out/package/apple"

    linux_cmake="$root/linux/CMakeLists.txt"
    linux_output="$root/out/package/linux/panopainter"

    webgl_cmake="$root/webgl/CMakeLists.txt"
    webgl_output="$root/out/package/webgl"

    file_available "$windows_wapproj"; windows_wapproj_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$windows_manifest"; windows_manifest_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available makeappx; makeappx_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available signtool; signtool_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$windows_output"; windows_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")

    file_available "$android_standard_gradle"; android_standard_gradle_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$android_standard_manifest"; android_standard_manifest_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$android_quest_gradle"; android_quest_gradle_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$android_quest_manifest"; android_quest_manifest_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$android_focus_gradle"; android_focus_gradle_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$android_focus_manifest"; android_focus_manifest_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available gradle; gradle_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$android_standard_output"; android_standard_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$android_quest_output"; android_quest_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$android_focus_output"; android_focus_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")

    file_available "$apple_project"; apple_project_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available xcodebuild; xcodebuild_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$apple_output"; apple_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")

    file_available "$linux_cmake"; linux_cmake_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available cmake; cmake_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    file_available "$linux_output"; linux_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")

    file_available "$webgl_cmake"; webgl_cmake_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available emcc; emcc_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    command_available emcmake; emcmake_exists=$([ $? -eq 0 ] && printf "1" || printf "0")
    dir_available "$webgl_output"; webgl_output_exists=$([ $? -eq 0 ] && printf "1" || printf "0")

    if is_kind_requested "windows-appx"; then
        windows_status="$(resolve_status 0 1 "$windows_wapproj_exists" "$windows_manifest_exists" "$makeappx_exists" "$signtool_exists")"
        windows_prerequisites=''
        windows_prerequisites="${windows_prerequisites}$(prerequisite_entry "legacy-wapproj" "$windows_wapproj_exists" "$windows_wapproj"),"
        windows_prerequisites="${windows_prerequisites}$(prerequisite_entry "appx-manifest" "$windows_manifest_exists" "$windows_manifest"),"
        windows_prerequisites="${windows_prerequisites}$(prerequisite_entry "makeappx" "$makeappx_exists" "Windows SDK packaging tool"),"
        windows_prerequisites="${windows_prerequisites}$(prerequisite_entry "signtool" "$signtool_exists" "Windows SDK signing tool"),"
        windows_prerequisites="${windows_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        windows_entry="{"
        windows_entry="${windows_entry}\"kind\":\"windows-appx\","
        windows_entry="${windows_entry}\"status\":\"$windows_status\","
        windows_entry="${windows_entry}\"reason\":\"legacy-wapproj-present-but-root-cmake-package-target-missing\","
        windows_entry="${windows_entry}\"debt\":\"DEBT-0011\","
        windows_entry="${windows_entry}\"validationCommand\":\"msbuild PanoPainterPackage/PanoPainterPackage.wapproj /p:Configuration=$configuration /p:Platform=x64\","
        windows_entry="${windows_entry}\"prerequisites\":[${windows_prerequisites}],"
        windows_entry="${windows_entry}\"artifacts\":["
        windows_entry="${windows_entry}$(artifact_entry "app-packages" "$windows_output" "Container")"
        windows_entry="${windows_entry}]}"
        append_json_item "$windows_entry"
    fi

    if is_kind_requested "android-standard-apk"; then
        android_standard_status="$(resolve_status 0 0 "$android_standard_gradle_exists" "$android_standard_manifest_exists" "$gradle_exists" "$android_native_standard_available")"
        android_standard_prerequisites=''
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "gradle-build" "$android_standard_gradle_exists" "$android_standard_gradle"),"
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "android-manifest" "$android_standard_manifest_exists" "$android_standard_manifest"),"
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "gradle" "$gradle_exists" "Android package builder"),"
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "retained-native-cmake-check" "$android_native_standard_available" "$android_native_standard_detail"),"
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "android-arm64/android-x64"),"
        android_standard_prerequisites="${android_standard_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        android_standard_entry="{"
        android_standard_entry="${android_standard_entry}\"kind\":\"android-standard-apk\","
        android_standard_entry="${android_standard_entry}\"status\":\"$android_standard_status\","
        android_standard_entry="${android_standard_entry}\"reason\":\"legacy-gradle-package-not-consuming-root-cmake-targets\","
        android_standard_entry="${android_standard_entry}\"debt\":\"DEBT-0011\","
        android_standard_entry="${android_standard_entry}\"validationCommand\":\"gradle -p android/android assembleDebug\","
        android_standard_entry="${android_standard_entry}\"prerequisites\":[${android_standard_prerequisites}],"
        android_standard_entry="${android_standard_entry}\"artifacts\":["
        android_standard_entry="${android_standard_entry}$(artifact_entry "apk-output" "$android_standard_output" "Container")"
        android_standard_entry="${android_standard_entry}]}"
        append_json_item "$android_standard_entry"
    fi

    if is_kind_requested "android-quest-apk"; then
        android_quest_status="$(resolve_status 0 0 "$android_quest_gradle_exists" "$android_quest_manifest_exists" "$gradle_exists" "$android_native_quest_available")"
        android_quest_prerequisites=''
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "gradle-build" "$android_quest_gradle_exists" "$android_quest_gradle"),"
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "android-manifest" "$android_quest_manifest_exists" "$android_quest_manifest"),"
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "gradle" "$gradle_exists" "Android package builder"),"
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "retained-native-cmake-check" "$android_native_quest_available" "$android_native_quest_detail"),"
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "android-quest-arm64"),"
        android_quest_prerequisites="${android_quest_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        android_quest_entry="{"
        android_quest_entry="${android_quest_entry}\"kind\":\"android-quest-apk\","
        android_quest_entry="${android_quest_entry}\"status\":\"$android_quest_status\","
        android_quest_entry="${android_quest_entry}\"reason\":\"legacy-gradle-package-not-consuming-root-cmake-targets\","
        android_quest_entry="${android_quest_entry}\"debt\":\"DEBT-0011\","
        android_quest_entry="${android_quest_entry}\"validationCommand\":\"gradle -p android/quest assembleDebug\","
        android_quest_entry="${android_quest_entry}\"prerequisites\":[${android_quest_prerequisites}],"
        android_quest_entry="${android_quest_entry}\"artifacts\":["
        android_quest_entry="${android_quest_entry}$(artifact_entry "apk-output" "$android_quest_output" "Container")"
        android_quest_entry="${android_quest_entry}]}"
        append_json_item "$android_quest_entry"
    fi

    if is_kind_requested "android-focus-apk"; then
        android_focus_status="$(resolve_status 0 0 "$android_focus_gradle_exists" "$android_focus_manifest_exists" "$gradle_exists" "$android_native_focus_available")"
        android_focus_prerequisites=''
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "gradle-build" "$android_focus_gradle_exists" "$android_focus_gradle"),"
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "android-manifest" "$android_focus_manifest_exists" "$android_focus_manifest"),"
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "gradle" "$gradle_exists" "Android package builder"),"
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "retained-native-cmake-check" "$android_native_focus_available" "$android_native_focus_detail"),"
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "android-focus-arm64"),"
        android_focus_prerequisites="${android_focus_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        android_focus_entry="{"
        android_focus_entry="${android_focus_entry}\"kind\":\"android-focus-apk\","
        android_focus_entry="${android_focus_entry}\"status\":\"$android_focus_status\","
        android_focus_entry="${android_focus_entry}\"reason\":\"legacy-gradle-package-not-consuming-root-cmake-targets\","
        android_focus_entry="${android_focus_entry}\"debt\":\"DEBT-0011\","
        android_focus_entry="${android_focus_entry}\"validationCommand\":\"gradle -p android/focus assembleDebug\","
        android_focus_entry="${android_focus_entry}\"prerequisites\":[${android_focus_prerequisites}],"
        android_focus_entry="${android_focus_entry}\"artifacts\":["
        android_focus_entry="${android_focus_entry}$(artifact_entry "apk-output" "$android_focus_output" "Container")"
        android_focus_entry="${android_focus_entry}]}"
        append_json_item "$android_focus_entry"
    fi

    if is_kind_requested "apple-bundle"; then
        apple_status="$(resolve_status 0 1 "$apple_project_exists" "$xcodebuild_exists")"
        apple_prerequisites=''
        apple_prerequisites="${apple_prerequisites}$(prerequisite_entry "legacy-xcode-project" "$apple_project_exists" "$apple_project"),"
        apple_prerequisites="${apple_prerequisites}$(prerequisite_entry "xcodebuild" "$xcodebuild_exists" "Apple package builder"),"
        apple_prerequisites="${apple_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "macos/ios-device/ios-simulator"),"
        apple_prerequisites="${apple_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        apple_entry="{"
        apple_entry="${apple_entry}\"kind\":\"apple-bundle\","
        apple_entry="${apple_entry}\"status\":\"$apple_status\","
        apple_entry="${apple_entry}\"reason\":\"legacy-xcode-project-and-host-toolchain-not-aligned-with-root-cmake-package-target\","
        apple_entry="${apple_entry}\"debt\":\"DEBT-0011\","
        apple_entry="${apple_entry}\"validationCommand\":\"xcodebuild -project PanoPainter.xcodeproj -configuration $configuration\","
        apple_entry="${apple_entry}\"prerequisites\":[${apple_prerequisites}],"
        apple_entry="${apple_entry}\"artifacts\":["
        apple_entry="${apple_entry}$(artifact_entry "apple-package-output" "$apple_output" "Container")"
        apple_entry="${apple_entry}]}"
        append_json_item "$apple_entry"
    fi

    if is_kind_requested "linux-app"; then
        linux_status="$(resolve_status 0 0 "$linux_cmake_exists" "$cmake_exists")"
        linux_prerequisites=''
        linux_prerequisites="${linux_prerequisites}$(prerequisite_entry "retained-linux-cmake" "$linux_cmake_exists" "$linux_cmake"),"
        linux_prerequisites="${linux_prerequisites}$(prerequisite_entry "cmake" "$cmake_exists" "Linux retained app CMake configure/build tool"),"
        linux_prerequisites="${linux_prerequisites}$(prerequisite_entry "retained-platform-cmake-baseline" 1 "python scripts/dev/check_retained_platform_cmake.py"),"
        linux_prerequisites="${linux_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "linux-clang"),"
        linux_prerequisites="${linux_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        linux_entry="{"
        linux_entry="${linux_entry}\"kind\":\"linux-app\","
        linux_entry="${linux_entry}\"status\":\"$linux_status\","
        linux_entry="${linux_entry}\"reason\":\"retained-linux-cmake-not-consuming-root-cmake-targets\","
        linux_entry="${linux_entry}\"debt\":\"DEBT-0011\","
        linux_entry="${linux_entry}\"validationCommand\":\"cmake -S linux -B out/package/linux-retained && cmake --build out/package/linux-retained --target panopainter\","
        linux_entry="${linux_entry}\"prerequisites\":[${linux_prerequisites}],"
        linux_entry="${linux_entry}\"artifacts\":["
        linux_entry="${linux_entry}$(artifact_entry "linux-app-output" "$linux_output" "Leaf")"
        linux_entry="${linux_entry}]}"
        append_json_item "$linux_entry"
    fi

    if is_kind_requested "webgl"; then
        webgl_status="$(resolve_status 0 0 "$webgl_cmake_exists" "$emcc_exists" "$emcmake_exists")"
        webgl_prerequisites=''
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "retained-webgl-cmake" "$webgl_cmake_exists" "$webgl_cmake"),"
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "emcc" "$emcc_exists" "Emscripten compiler"),"
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "emcmake" "$emcmake_exists" "Emscripten CMake wrapper"),"
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "retained-platform-cmake-baseline" 1 "python scripts/dev/check_retained_platform_cmake.py"),"
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "root-cmake-preset" 1 "emscripten"),"
        webgl_prerequisites="${webgl_prerequisites}$(prerequisite_entry "root-cmake-package-target" 0 "Not migrated yet")"
        webgl_entry="{"
        webgl_entry="${webgl_entry}\"kind\":\"webgl\","
        webgl_entry="${webgl_entry}\"status\":\"$webgl_status\","
        webgl_entry="${webgl_entry}\"reason\":\"retained-webgl-cmake-not-consuming-root-cmake-targets\","
        webgl_entry="${webgl_entry}\"debt\":\"DEBT-0011\","
        webgl_entry="${webgl_entry}\"validationCommand\":\"emcmake cmake -S webgl -B out/package/webgl-retained && cmake --build out/package/webgl-retained --target panopainter\","
        webgl_entry="${webgl_entry}\"prerequisites\":[${webgl_prerequisites}],"
        webgl_entry="${webgl_entry}\"artifacts\":["
        webgl_entry="${webgl_entry}$(artifact_entry "webgl-output" "$webgl_output" "Container")"
        webgl_entry="${webgl_entry}]}"
        append_json_item "$webgl_entry"
    fi

    printf "[%s]" "$package_readiness"
}

build_android_native_validation

if [ "$readiness_only" -eq 1 ]; then
    elapsed_ms="$(( ( $(date +%s) - start ) * 1000 ))"
    package_readiness="$(build_package_readiness)"
    printf '{"command":"package-smoke",'
    printf '"preset":%s,"configuration":%s,"target":%s,' \
        "$(json_string "$preset")" \
        "$(json_string "$configuration")" \
        "$(json_string "$target")"
    printf '"stage":"readiness","exitCode":0,"elapsedMs":%s,' "$elapsed_ms"
    printf '"androidNativeValidation":%s,' "$android_native_validation"
    printf '"packageReadiness":%s}\n' "$package_readiness"
    exit 0
fi

$cmake_command --build --preset "$preset" --config "$configuration" --target "$target"
build_exit="$?"
if [ "$build_exit" -ne 0 ]; then
    elapsed_ms="$(( ( $(date +%s) - start ) * 1000 ))"
    package_readiness="$(build_package_readiness)"
    printf '{"command":"package-smoke",'
    printf '"preset":%s,"configuration":%s,"target":%s,' \
        "$(json_string "$preset")" \
        "$(json_string "$configuration")" \
        "$(json_string "$target")"
    printf '"cmakeCommand":%s,' "$(json_string "$cmake_command")"
    printf '"stage":"build","exitCode":%s,"elapsedMs":%s,' "$build_exit" "$elapsed_ms"
    printf '"androidNativeValidation":%s,' "$android_native_validation"
    printf '"packageReadiness":%s}\n' "$package_readiness"
    exit "$build_exit"
fi

binary="${root}/out/build/$preset/$configuration/$target.exe"
binary_dir="$(printf '%s' "$binary" | sed 's#/[^/]*$##')"
data_dir="$binary_dir/data"
curl_dll="$(
    if [ "$configuration" = "Debug" ]; then
        printf "libcurl_debug.dll"
    else
        printf "libcurl.dll"
    fi
)"

checks=''
checks="${checks}$(check_entry "executable" "$binary" "$([ -f "$binary" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "data" "$data_dir" "$([ -d "$data_dir" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "BugTrapU-x64.dll" "$binary_dir/BugTrapU-x64.dll" "$([ -f "$binary_dir/BugTrapU-x64.dll" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "$curl_dll" "$binary_dir/$curl_dll" "$([ -f "$binary_dir/$curl_dll" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "libyuv.dll" "$binary_dir/libyuv.dll" "$([ -f "$binary_dir/libyuv.dll" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "libmp4v2.dll" "$binary_dir/libmp4v2.dll" "$([ -f "$binary_dir/libmp4v2.dll" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "openh264-2.0.0-win64.dll" "$binary_dir/openh264-2.0.0-win64.dll" "$([ -f "$binary_dir/openh264-2.0.0-win64.dll" ] && printf "1" || printf "0")"),"
checks="${checks}$(check_entry "openvr_api.dll" "$binary_dir/openvr_api.dll" "$([ -f "$binary_dir/openvr_api.dll" ] && printf "1" || printf "0")")"

artifact_exists="$( [ -e "$artifact" ] && printf 1 || printf 0 )"
exit_code=0
if [ "$artifact_exists" -eq 0 ]; then
    exit_code=2
fi
if [ "$android_native_checks" -ne 0 ] && [ "$exit_code" -eq 0 ]; then
    exit_code="$(echo "$android_native_validation" | sed -n 's/.*"exitCode":[[:space:]]*\\([0-9][0-9]*\\).*/\\1/p')"
    if [ "$exit_code" -eq 0 ]; then
        exit_code=0
    else
        exit_code=1
    fi
fi

package_readiness="$(build_package_readiness)"
elapsed_ms="$(( ( $(date +%s) - start ) * 1000 ))"

printf '{"command":"package-smoke",'
printf '"preset":%s,"configuration":%s,"target":%s,' \
    "$(json_string "$preset")" \
    "$(json_string "$configuration")" \
    "$(json_string "$target")"
printf '"artifact":%s,"exists":%s,"cmakeCommand":%s,' \
    "$(json_string "$artifact")" \
    "$(json_bool "$artifact_exists")" \
    "$(json_string "$cmake_command")"
printf '"exitCode":%s,"elapsedMs":%s,' "$exit_code" "$elapsed_ms"
printf '"checks":[%s],' "$checks"
printf '"androidNativeValidation":%s,' "$android_native_validation"
printf '"packageReadiness":%s}\n' "$package_readiness"
exit "$exit_code"
