#!/bin/sh

metadata_get() {
    fastboot -s "${TARGET_DEVICE_SERIAL}" getvar "$1" 2>&1 | grep -oP "${1}"': \K[^\r\n]*'
}

metadata_gather() {
    announce_start "Metadata extraction"
    
    ETH_MAC_ADDRESS=$(metadata_get "mac-ethernet")
    WIFI_MAC_ADDRESS=$(metadata_get "mac-wifi")
    BT_MAC_ADDRESS=$(metadata_get "mac-bt")
    
    MMC_SECTOR_SIZE=$(metadata_get "mmc-sector-size")
    MMC_SECTOR_SIZE=${MMC_SECTOR_SIZE:-0}
    MMC_SECTOR_COUNT=$(metadata_get "mmc-sector-count")
    MMC_SECTOR_COUNT=${MMC_SECTOR_COUNT:-0}
    MMC_SIZE=$(( MMC_SECTOR_SIZE * MMC_SECTOR_COUNT ))
    MMC_CID=$(metadata_get "mmc-cid")
    MMC_CID=${MMC_CID:-""}
    
    RPI_DUID=$(metadata_get "rpi-duid")
    
    TYPE=$(metadata_get "revision-type")
    PROCESSOR=$(metadata_get "revision-processor")
    MEMORY=$(metadata_get "revision-memory")
    MANUFACTURER=$(metadata_get "revision-manufacturer")
    REVISION=$(metadata_get "revision-revision")
    SECURE=$(metadata_get "secure")
    
    case ${TYPE} in
        "0x06") BOARD_STR="CM1" ;;
        "0x08") BOARD_STR="3B" ;;
        "0x09") BOARD_STR="Zero" ;;
        "0x0A") BOARD_STR="CM3" ;;
        "0x0C") BOARD_STR="Zero W" ;;
        "0x0D") BOARD_STR="3B+" ;;
        "0x0E") BOARD_STR="3A+" ;;
        "0x10") BOARD_STR="CM3+" ;;
        "0x11") BOARD_STR="4B" ;;
        "0x12") BOARD_STR="Zero 2 W" ;;
        "0x13") BOARD_STR="400" ;;
        "0x14") BOARD_STR="CM4" ;;
        "0x15") BOARD_STR="CM4S" ;;
        "0x17") BOARD_STR="5" ;;
        "0x18") BOARD_STR="CM5" ;;
        "0x19") BOARD_STR="500" ;;
        "0x1a") BOARD_STR="CM5 Lite" ;;
        *)
            BOARD_STR="Unsupported Board: ${TYPE}"
    esac
    
    case ${PROCESSOR} in
        "0x0") PROCESSOR_STR="BCM2835" ;;
        "0x1") PROCESSOR_STR="BCM2836" ;;
        "0x2") PROCESSOR_STR="BCM2837" ;;
        "0x3") PROCESSOR_STR="BCM2711" ;;
        "0x4") PROCESSOR_STR="BCM2712" ;;
        *)
            PROCESSOR_STR="Unknown: ${PROCESSOR}"
    esac
    
    case ${MEMORY} in
        "0x0") MEMORY_STR="256MB" ;;
        "0x1") MEMORY_STR="512MB" ;;
        "0x2") MEMORY_STR="1GB" ;;
        "0x3") MEMORY_STR="2GB" ;;
        "0x4") MEMORY_STR="4GB" ;;
        "0x5") MEMORY_STR="8GB" ;;
        "0x6") MEMORY_STR="16GB" ;;
        *)
            MEMORY_STR="Unknown: ${MEMORY}"
    esac
    
    case ${MANUFACTURER} in
        "0x0") MANUFACTURER_STR="Sony UK" ;;
        "0x1") MANUFACTURER_STR="Egoman" ;;
        "0x2") MANUFACTURER_STR="Embest" ;;
        "0x3") MANUFACTURER_STR="Sony Japan" ;;
        "0x4") MANUFACTURER_STR="Embest" ;;
        "0x5") MANUFACTURER_STR="Stadium" ;;
        *)
            MANUFACTURER_STR="Unknown: ${MANUFACTURER}"
    esac
    
    echo "Board is: ${BOARD_STR}, with revision number ${REVISION}. Has Processor ${PROCESSOR_STR} with Memory ${MEMORY_STR}. Was manufactured by ${MANUFACTURER_STR}"
    
    if [ -f "${RPI_SB_PROVISIONER_MANUFACTURING_DB}" ]; then
        announce_start "Manufacturing Database Insertion"
        check_command_exists sqlite3
        
        # Ensure WAL journal mode
        sqlite3 "${RPI_SB_PROVISIONER_MANUFACTURING_DB}" "PRAGMA journal_mode=WAL;" > /dev/null 2>&1
        
        # Define the schema for devices table
        # Security tracking fields default to NULL to distinguish between not-applied vs unknown state
        EXPECTED_SCHEMA="id              integer primary key,
                    boardname       varchar(255)        not null,
                    serial          char(8)             not null,
                    eth_mac         char(17)            not null,
                    wifi_mac        char(17)            not null,
                    bt_mac          char(17)            not null,
                    mmc_size        integer             not null,
                    mmc_cid         char(32)            not null,
                    rpi_duid        char(32)            not null,
                    board_revision  varchar(255)        not null,
                    processor       varchar(255)        not null,
                    memory          varchar(255)        not null,
                    manufacturer    varchar(255)        not null,
                    secure          integer             not null,
                    jtag_locked     integer             DEFAULT NULL,
                    eeprom_write_protected integer      DEFAULT NULL,
                    pubkey_programmed integer           DEFAULT NULL,
                    devkey_revoked   integer           DEFAULT NULL,
                    signed_boot_enabled integer         DEFAULT NULL,
                    os_image_filename varchar(255)      DEFAULT NULL,
                    os_image_sha256  char(64)           DEFAULT NULL,
                    provision_ts    timestamp           default current_timestamp"
        
        # Check if the table exists
        TABLE_EXISTS=$(sqlite3 "${RPI_SB_PROVISIONER_MANUFACTURING_DB}" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='devices';")
        
        if [ "$TABLE_EXISTS" -eq 0 ]; then
            # Table doesn't exist, create it
            sqlite3 "${RPI_SB_PROVISIONER_MANUFACTURING_DB}" "CREATE TABLE devices($EXPECTED_SCHEMA);" > /dev/null 2>&1
        fi
        
        # Determine security flags based on provisioning configuration
        # JTAG lock status: 1 if enabled, 0 if explicitly disabled, NULL if not configured
        JTAG_LOCKED_VALUE="NULL"
        if [ -n "${RPI_DEVICE_LOCK_JTAG}" ]; then
            JTAG_LOCKED_VALUE="1"
        elif [ "${SECURE}" = "1" ]; then
            # For secure provisioning, explicitly track that JTAG locking was not enabled
            JTAG_LOCKED_VALUE="0"
        fi
        
        # EEPROM write protection status: 1 if enabled, 0 if explicitly disabled, NULL if not configured  
        EEPROM_WP_VALUE="NULL"
        if [ -n "${RPI_DEVICE_EEPROM_WP_SET}" ]; then
            EEPROM_WP_VALUE="1"
        elif [ "${SECURE}" = "1" ]; then
            # For secure provisioning, explicitly track that EEPROM WP was not enabled
            EEPROM_WP_VALUE="0"
        fi
        
        # Public key programming: read from fastboot metadata 'signed-otp'
        # Map 'present' -> 1, 'not present' -> 0, common boolean forms as fallback, else NULL
        PUBKEY_PROGRAMMED_VALUE="NULL"
        SIGNED_OTP="$(metadata_get "secure-otp")"
        if [ -n "${SIGNED_OTP}" ]; then
            SIGNED_OTP_LC="$(printf "%s" "${SIGNED_OTP}" | tr '[:upper:]' '[:lower:]')"
            case "${SIGNED_OTP_LC}" in
                present|1|true|yes)
                    PUBKEY_PROGRAMMED_VALUE="1"
                    ;;
                "not present"|notpresent|0|false|no)
                    PUBKEY_PROGRAMMED_VALUE="0"
                    ;;
                *)
                    : # leave as NULL
                    ;;
            esac
        fi
        
        # Dev key revoked (signed-devkey): 'present' -> 1, 'not present' -> 0, else NULL
        DEVKEY_REVOKED_VALUE="NULL"
        SIGNED_DEVKEY="$(metadata_get "secure-devkey")"
        if [ -n "${SIGNED_DEVKEY}" ]; then
            SIGNED_DEVKEY_LC="$(printf "%s" "${SIGNED_DEVKEY}" | tr '[:upper:]' '[:lower:]')"
            case "${SIGNED_DEVKEY_LC}" in
                present)
                    DEVKEY_REVOKED_VALUE="1"
                    ;;
                "not present"|notpresent)
                    DEVKEY_REVOKED_VALUE="0"
                    ;;
                *)
                    : ;;
            esac
        fi

        # Signed boot: 1 for secure provisioning, 0 for non-secure, NULL for unknown
        SIGNED_BOOT_VALUE="NULL"
        if [ "${SECURE}" = "1" ]; then
            SIGNED_BOOT_VALUE="1"
        elif [ "${SECURE}" = "0" ]; then
            SIGNED_BOOT_VALUE="0"
        fi

	        # Determine OS image metadata if available
	        OS_IMAGE_FILENAME=""
	        OS_IMAGE_SHA256=""
	        if [ -n "${GOLD_MASTER_OS_FILE}" ] && [ -f "${GOLD_MASTER_OS_FILE}" ]; then
	            OS_IMAGE_FILENAME="$(basename -- "${GOLD_MASTER_OS_FILE}")"
	            # Prefer sidecar file written by UI backend: <image>.sha256 (first token/line)
	            if [ -f "${GOLD_MASTER_OS_FILE}.sha256" ]; then
	                # Read first non-empty token from sidecar
	                OS_IMAGE_SHA256="$(head -n1 "${GOLD_MASTER_OS_FILE}.sha256" | awk '{print $1}')"
	            fi
	            # Fallback to calculating if sidecar missing or empty
	            if [ -z "${OS_IMAGE_SHA256}" ] && command -v sha256sum >/dev/null 2>&1; then
	                OS_IMAGE_SHA256="$(sha256sum "${GOLD_MASTER_OS_FILE}" | awk '{print $1}')"
	                # Best-effort: persist to sidecar for reuse by UI and future runs
	                printf '%s\n' "${OS_IMAGE_SHA256}" > "${GOLD_MASTER_OS_FILE}.sha256" 2>/dev/null || true
	            fi
	        fi

        # Insert new device data
        sqlite3 "${RPI_SB_PROVISIONER_MANUFACTURING_DB}" \
        "INSERT INTO devices(           \
                    boardname,                  \
                    serial,                     \
                    eth_mac,                    \
                    wifi_mac,                   \
                    bt_mac,                     \
                    mmc_size,                   \
                    mmc_cid,                    \
                    rpi_duid,                   \
                    board_revision,             \
                    processor,                  \
                    memory,                     \
                    manufacturer,               \
                    secure,                     \
                    jtag_locked,                \
                    eeprom_write_protected,     \
                    pubkey_programmed,          \
                    devkey_revoked,             \
                    signed_boot_enabled,        \
                    os_image_filename,          \
                    os_image_sha256             \
                ) VALUES (                      \
                    '${BOARD_STR}',               \
                    '${TARGET_DEVICE_SERIAL}',    \
                    '${ETH_MAC_ADDRESS}',         \
                    '${WIFI_MAC_ADDRESS}',        \
                    '${BT_MAC_ADDRESS}',          \
                    '${MMC_SIZE}',                \
                    '${MMC_CID}',                 \
                    '${RPI_DUID}',                \
                    '${REVISION}',                \
                    '${PROCESSOR_STR}',           \
                    '${MEMORY_STR}',              \
                    '${MANUFACTURER_STR}',        \
                    '${SECURE}',                  \
                    ${JTAG_LOCKED_VALUE},         \
                    ${EEPROM_WP_VALUE},           \
                    ${PUBKEY_PROGRAMMED_VALUE},   \
                    ${DEVKEY_REVOKED_VALUE},      \
                    ${SIGNED_BOOT_VALUE},         \
                    '${OS_IMAGE_FILENAME}',       \
                    '${OS_IMAGE_SHA256}'          \
        );" > /dev/null 2>&1
        announce_stop "Manufacturing Database Insertion"
    fi
    announce_stop "Metadata extraction"
}
