#!/bin/bash

project_root="$PWD"

# Source the utils.sh file
source "$project_root/TOOLS/helpers/utils.sh" "$project_root"

# 0 arguments: interactive mode
# 1 argument: firmware file or configuration file
# 2 arguments: firmware file and configuration file
usage() {
    echo "usage : $0 [firmware_file] [configuration_file]"
    exit 1
}

# check the required tools
check_tools "awk zip app_version.sh app_model.sh ack2_swu_encrypt.py python3"

# set the custom encrypt tool
ENCRYPT_TOOL=$(which "ack2_swu_encrypt.py")
if [ -z "$ENCRYPT_TOOL" ]; then
    # if not installed use the local copy
    ENCRYPT_TOOL="TOOLS/ack2_swu_encrypt.py"
fi

# selected fw file
selected_firmware_file=""

# selected config file
selected_config_file="options.cfg"

# check first for a default file set by update.bin|zip|swu
default_firmware_file=""
if [ -f "$FW_DIR/update.swu" ]; then
    default_firmware_file="$FW_DIR/update.swu"
elif [ -f "$FW_DIR/update.zip" ]; then
    default_firmware_file="$FW_DIR/update.zip"
elif [ -f "$FW_DIR/update.bin" ]; then
    default_firmware_file="$FW_DIR/update.bin"
fi

if [ $# -eq 0 ]; then
    # no arguments provided
    if [ -n "$default_firmware_file" ]; then
        # but default file exists, use it
        selected_firmware_file="$default_firmware_file"
    fi
elif [ $# -eq 1 ]; then
    # one argument provided
    fw_file="$1"
    fw_file_ext="${fw_file##*.}"
    if [ "$fw_file_ext" = "swu" ] || [ "$fw_file_ext" = "bin" ] || [ "$fw_file_ext" = "zip" ]; then
        if [ -f "$fw_file" ]; then
            # it is a valid firmware file
            selected_firmware_file="$fw_file"
        elif [ -f "$FW_DIR/$fw_file" ]; then
            selected_firmware_file="$FW_DIR/$fw_file"
        else
            usage
        fi
    else
        cfg_file="$project_root/$1"
        if [ -f "$cfg_file" ]; then
            # it is a configuration file with ext
            selected_config_file="$cfg_file"
        elif [ -f "${cfg_file}.cfg" ]; then
            echo "${cfg_file}.cfg"
            # it is a configuration file without ext
            selected_config_file="${cfg_file}.cfg"
        else
            usage
        fi
        selected_firmware_file="$default_firmware_file"
    fi
elif [ $# -eq 2 ]; then
    # two arguments provided
    fw_file="$1"
    fw_file_ext="${fw_file##*.}"
    if [ "$fw_file_ext" = "swu" ] || [ "$fw_file_ext" = "bin" ] || [ "$fw_file_ext" = "zip" ]; then
        if [ -f "$fw_file" ]; then
            # it is a valid firmware file
            selected_firmware_file="$fw_file"
        elif [ -f "$FW_DIR/$fw_file" ]; then
            selected_firmware_file="$FW_DIR/$fw_file"
        else
            usage
        fi
    else
        usage
    fi
    cfg_file="$project_root/$2"
    if [ -f "$cfg_file" ]; then
        # it is a configuration file with ext
        selected_config_file="$cfg_file"
    elif [ -f "${cfg_file}.cfg" ]; then
        # it is a configuration file without ext
        selected_config_file="${cfg_file}.cfg"
    else
        usage
    fi
elif [ $# -ge 3 ]; then
    # 3 or more arguments provided
    usage
fi

# check the config file for build_input and build_output options
build_input=""
build_output=""
auto_install_tool=""
if [ -f "$selected_config_file" ]; then

    # parse the enabled options that have a set value
    options=$(awk -F '=' '{if (! ($0 ~ /^;/) && ! ($0 ~ /^#/) && ! ($0 ~ /^$/) && ! ($2 == "")) print $1}' "$selected_config_file")

    # for each enabled option
    for option in $options; do
        parameters=$(awk -F '=' "{if (! (substr(\$0,1,1) == \"#\") && ! (substr(\$0,1,1) == \";\") && ! (\$1 == \"\") && ! (\$2 == \"\") && (\$1 ~ /$option/ ) ) print \$2}" "$selected_config_file" | head -n 1)
        # replace the project root requests
        parameter="${parameters/@/"$project_root"}"
        # remove the leading and ending double quotes
        parameter=$(echo "$parameter" | sed -e 's/^"//' -e 's/"$//')
        # remove the leading and ending single quotes
        parameter=$(echo "$parameter" | sed -e 's/^'\''//' -e 's/'\''$//')
        if [ "$option" = "build_input" ]; then
            build_input="$parameter"
        fi
        if [ "$option" = "build_output" ]; then
            build_output="$parameter"
        fi
        if [ "$option" = "auto_install" ]; then
            auto_install_tool="$parameter"
        fi
    done
fi

if [ -z "$selected_firmware_file" ] && [ -n "$build_input" ] && [ -f "$build_input" ]; then
    # no fw file provided but the config file has a valid fw file set, use that file
    selected_firmware_file="$build_input"
fi

if [ -z "$selected_firmware_file" ]; then

    # No firmware file selected by the user: interactive mode

    # Check if firmware exists in the FW folder else ask the user to download it

    # List all files in $FW_DIR and check if there are any files .zip, .bin or .swu
    # If there are files, ask the user if they want to use the files in the FW folder else ask the user to download the firmware

    # Get all files in the FW folder that are .zip, .bin or .swu
    all_files=$(ls $FW_DIR | grep -E ".zip|.bin|.swu")

    # If there are no files in the FW folder, ask the user to download the firmware
    if [ -z "$all_files" ]; then
        read -p "No firmware files found in the FW folder. Do you want to download the firmware? (y/n) " -n 1 -r
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            echo
            read -p "Enter version: " par_version
            read -p "Enter model: " par_model
            echo "Downloading firmware..."
            #  Run fwdl.sh with the model and version as parameters
            $project_root/fwdl.sh $par_model $par_version
            all_files=$(ls $FW_DIR | grep -E ".zip|.bin|.swu")
        else
            echo
            echo "Please download the firmware and place it in the FW folder"
            exit 2
        fi
    fi

    # If there are files in the FW folder, ask the user if they want to use the files in the FW folder
    if [ -n "$all_files" ]; then
        #   List all firmwares and ask user to pick an available firmware version
        echo "Available firmware versions:"
        for file in $all_files; do
            echo $file
        done
        read -p "Which file do you want to use? " firmware_file
        if [ -f "$FW_DIR/$firmware_file" ]; then
            echo "Using firmware $firmware_file"
        else
            echo "Firmware file not found"
            exit 3
        fi
    fi
    selected_firmware_file="$FW_DIR/$firmware_file"
fi

# Unpack the firmware
echo "Unpacking firmware..."
"$project_root/unpack.sh" "$selected_firmware_file"
if [ $? -ne 0 ]; then
    echo "Failed to unpack firmware"
    exit 4
fi

# Patch the firmware
echo "Patching firmware..."
"$project_root/patch.sh" "$selected_config_file"
if [ $? -ne 0 ]; then
    echo "Failed to patch firmware"
    exit 5
fi

# Build the firmware
echo "Building firmware..."
"$project_root/pack.sh"
if [ $? -ne 0 ]; then
    echo "Failed to build firmware"
    exit 6
fi

# Process the output file if set
if [ -n "$build_output" ]; then

    # try to find out the app version (like app_ver="3.1.0")
    def_target="$ROOTFS_DIR/app/app"
    app_ver=$("$app_version_tool" "$def_target")
    if [ $? != 0 ]; then
        echo -e "${RED}ERROR: Cannot find the app version ${NC}"
        exit 4
    fi

    # try to find out the model
    app_model=$("$app_model_tool" "$def_target")
    if [ $? != 0 ]; then
        echo -e "${RED}ERROR: Cannot find the app model ${NC}"
        exit 5
    fi

    rm -f "$project_root/update.bin"
    rm -f "$project_root/update.zip"
    zip -r "$project_root/update.zip" update
    $ENCRYPT_TOOL -i "$project_root/update.zip" -o "$project_root/update.bin" -m "$app_model" -v "$app_ver"
    /bin/cp -f "$project_root/update.bin" "$build_output"
    rm -f "$project_root/update.zip"
    rm -f "$project_root/update.bin"
fi

# use the auto install tool if present
if [ -f "$auto_install_tool" ]; then
    # Ask if the user wants to attempt to auto install the update now. If yes then run the auto install script
    read -r -p "Do you want to attempt to auto install the update? [y/N] " response
    if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
        # Run the auto update tool
        if [[ "$auto_install_tool" == *.py ]]; then
            python3 "$auto_install_tool"
        else
            "$auto_install_tool"
        fi
    fi
fi

echo
echo -e "${YELLOW}Selected firmware file: $selected_firmware_file ${NC}"
echo -e "${YELLOW}Selected configuration file: $selected_config_file ${NC}"
echo -e "${GREEN}Firmware build complete ${NC}"
echo

exit 0
