UPGRADE_FW_MAJOR="2022-09-13-0-11012d53-22.08-plus"
UPGRADE_FW_VERSION="2026-05-07-0-e6eaa788-26.05-plus"
UPGRADE_FW_REQUIRE="2022-09-13-0-11012d53-22.08-plus"
current_fw_version() {
    cat /etc/bos_version
}

current_fw_major() {
    cat /etc/bos_major
}

check_fw_version() {
    echo "Gathering current firmware information..."

    local board_name=$1
    local fw_major=$(current_fw_major)
    local fw_version=$(current_fw_version)

    echo "board  : $board_name"
    echo "version: $fw_version"
    echo "major  : $fw_major"

    echo "Checking compatibility..."

    if [ "$UPGRADE_FW_VERSION" ">" "$fw_version" ]; then
        # firmware upgrade
        if [ "$UPGRADE_FW_REQUIRE" ">" "$fw_version" ]; then
            echo "Firmware upgrade to '$UPGRADE_FW_VERSION' is not possible!"
            echo "Firmware version '$UPGRADE_FW_REQUIRE' is required before upgrading to this version."
            return 1
        fi
    elif [ "$UPGRADE_FW_VERSION" "<" "$fw_version" ]; then
        # firmware downgrade
        if [ "$UPGRADE_FW_MAJOR" != "$fw_major" ]; then
            echo "Firmware downgrade to '$UPGRADE_FW_VERSION' is not possible!"
            echo "Downgrade is only possible among firmwares with major version '$UPGRADE_FW_MAJOR'."
            echo "Do the factory reset and try to upgrade to this version."
            return 1
        fi
    fi

    return 0
}

# Check if /etc has enough space (1MB) for logging during upgrade, and free
free_space_etc() {
    # Check if /etc has at least 1MiB free space
    local required_space=1024
    local etc_free=$(df | grep /etc | awk '{print $4}')

    # If we already have enough space, return success
    if [ "$etc_free" -ge "$required_space" ]; then
        return 0
    fi

    # Get used space for /var/log/metrics
    local metrics_used=$(du -s /var/log/metrics 2>/dev/null | awk '{print $1}')
    # Handle case where directory doesn't exist or is empty
    [ -z "$metrics_used" ] && metrics_used=0

    # Check if freeing metrics logs would give us enough space
    if [ $((etc_free + metrics_used)) -ge "$required_space" ]; then
        rm -rf /var/log/metrics/*
        return 0
    fi

    # Not enough space even after freeing logs
    return 1
}

check_image() {
    free_space_etc || {
        echo "Not enough free space in /etc for logging during upgrade."
        echo "Please free up some space and try again."
        return 1
    }
    check_fw_version $1
}

do_upgrade_sd() {
    local package_root="$1"
    local sdcard_root="$2"

    echo "    rootfs.img"
    cp "$package_root/rootfs.img" "$sdcard_root/"

    return 0
}

# Get file size in decimal number if second parameter is 10
# otherwise return files size in hexadecimal number
file_size() {
    number_base=$2
    decimal_file_size="$(wc -c < "$1")"
    if [ "$number_base" = "10" ]; then
        echo "$decimal_file_size"
        return 0
    fi
    printf "0x%x" "$decimal_file_size"
}

do_upgrade_nand() {
    local image_file="$1"
    local install_partition="$2"
    # Get the package root directory from the image file path
    local package_root="$(dirname "$image_file")"

    # Load constant "$BOS_ENV_FILE"
    . /lib/functions/common.sh

    flash_eraseall "$install_partition"
    nandwrite -p "$install_partition" "$image_file"

    # "STOCK_UBOOT_ENV_PARTITION_BOS_LAYOUT" is currently not included in the common.sh
    # so we have to define it here
    STOCK_UBOOT_ENV_PARTITION_BOS_LAYOUT="/dev/mtd1"

    # Get size of the new env file so we know how much to dump
    env_size=$(file_size "$package_root/$BOS_ENV_FILE")

    cat $package_root/$BOS_ENV_FILE | sha256sum > /tmp/$BOS_ENV_FILE.checksum
    if nanddump -l $env_size "$STOCK_UBOOT_ENV_PARTITION_BOS_LAYOUT" | \
       sha256sum -c /tmp/$BOS_ENV_FILE.checksum &>/dev/null; then
        # Env is the same, no need to update
        return 0
    fi

    # Env is different, erase and write new env
    flash_eraseall "$STOCK_UBOOT_ENV_PARTITION_BOS_LAYOUT" || return 1
    nandwrite -p "$STOCK_UBOOT_ENV_PARTITION_BOS_LAYOUT" "$package_root/$BOS_ENV_FILE"

    return 0
}

do_upgrade() {
    # For backward compatibility with only sd version we have to keep do_upgrade naming of function
    # TODO: when major version is released this backward compatibility can be removed

    local package_root="$1"
    local sdcard_root="$2"

    do_upgrade_sd $package_root $sdcard_root
}
