#!/bin/sh

. /usr/share/libubox/jshn.sh
. /lib/upgrade/iopsys.sh
. /lib/upgrade/platform.sh

. /lib/functions/iopsys-system-layout.sh

. /lib/functions/iopsys-fwbank.sh

# Local cache used to store system layout variables we use in tmpfs.
# Stored in the $iop_bank_prefix directory.
fwbank_cache_file="sl_cache"
fwbank_sl_cache="$iop_bank_prefix/$fwbank_cache_file"

# Wrapper, checking if platform_get_bootbank() exists, and calling it if so.
fwbank_get_bootbank() {
	if type platform_get_bootbank >/dev/null 2>/dev/null; then
		platform_get_bootbank
	fi
}

case "$1" in
	list)
		echo '{ "dump" : {}, "set_bootbank" : {"bank":32}, "copy_config" : {}, "upgrade": {"path":"String","auto_activate":true,"bank":32,"keep_settings":true}}'
	;;
	call)
		case "$2" in
			dump)
				# Get the system layout variables we use, either from
				# the cache or load them fresh by calling the function.
				if [ -r "$fwbank_sl_cache" ]; then
					source "$fwbank_sl_cache"
				else
					get_system_layout_info_in_global_var

					# Fill the private cache for our purposes
					mkdir -p "$iop_bank_prefix"
					echo "SL_current_bank_id=$SL_current_bank_id" > "$fwbank_sl_cache"
					echo "SL_current_bank_name=$SL_current_bank_name" >> "$fwbank_sl_cache"
					echo "SL_other_bank_id=$SL_other_bank_id" >> "$fwbank_sl_cache"
					echo "SL_other_bank_name=$SL_other_bank_name" >> "$fwbank_sl_cache"
				fi

				json_init
				# Sanity check
				if [ -z "${SL_current_bank_id}" ]; then
					json_dump
					exit 0
				fi

				# Fill in this bank's object
				# Get this bank's firmware version
				fwver_current="$(iopsys_get_fwbank_fwver ${SL_current_bank_id})"
				swver_current="$(iopsys_get_fwbank_swver ${SL_current_bank_id})"
				omci_swver_current="$(iopsys_get_fwbank_omci_swver ${SL_current_bank_id})"

				fwver_other="$(iopsys_get_fwbank_fwver ${SL_other_bank_id})"
				swver_other="$(iopsys_get_fwbank_swver ${SL_other_bank_id})"
				omci_swver_other="$(iopsys_get_fwbank_omci_swver ${SL_other_bank_id})"

				# Fill in info on which bank is going to boot next
				bootbank="$(fwbank_get_bootbank)"
				[ "${bootbank}" == "${SL_current_bank_id}" ] && boot_current=1 || boot_current=0
				[ "${bootbank}" == "${SL_other_bank_id}" ] && boot_other=1 || boot_other=0

				json_add_array "bank"

				for i in $(seq 1 2); do
					if [ ${i} == ${SL_current_bank_id} ]; then
						json_add_object ""
						json_add_string "name" ${SL_current_bank_name}
						json_add_int "id" ${SL_current_bank_id}
						json_add_boolean "active" 1
						json_add_boolean "boot" ${boot_current}
						json_add_boolean "upgrade" 0
						json_add_string "fwver" "${fwver_current}"
						json_add_string "swver" "${swver_current}"
						json_add_string "omci_swver" "${omci_swver_current}"
						json_add_string "status" "$(iopsys_get_fwbank_status ${SL_current_bank_id})"
						json_select ..
					else
						json_add_object ""
						json_add_string "name" $SL_other_bank_name
						json_add_int "id" $SL_other_bank_id
						json_add_boolean "active" 0
						json_add_boolean "boot" ${boot_other}
						json_add_boolean "upgrade" 1
						json_add_string "fwver" "${fwver_other}"
						json_add_string "swver" "${swver_other}"
						json_add_string "omci_swver" "${omci_swver_other}"
						json_add_string "status" "$(iopsys_get_fwbank_status ${SL_other_bank_id})"
						json_select ..
					fi
				done

				# End of our two banks, end of array
				json_close_array
				json_dump
			;;
			set_bootbank)
				read -r input
				json_load "$input"
				json_get_var bank bank

				# Redirect any output that this function might be printing
				# to stderr, to keep stdout clean. This avoids problems with
				# the caller of this ubus method, as only valid JSON is expected
				# on stdout.
				if type platform_set_bootbank >/dev/null 2>/dev/null; then
					platform_set_bootbank "$bank" 1>&2
				fi

				bootbank="$(fwbank_get_bootbank)"

				if [ -z "${bank}" -o -z "${bootbank}" ]; then
					echo '{"success": false}'
					exit 0
				fi

				if [ "${bank}" == "${bootbank}" ]; then
					echo '{"success": true}'
				else
					echo '{"success": false}'
				fi
			;;
			copy_config)
				if [ -z "$UPGRADE_BACKUP" ]; then
					UPGRADE_BACKUP=/tmp/sysupgrade.tgz
				fi

				ret=0

				sysupgrade -b "$UPGRADE_BACKUP" || ret=1

				if [ "$ret" -eq 0 ]; then
					if command -v platform_copy_config >/dev/null 2>&1; then
						platform_copy_config 1>&2 || ret=1
					else
						ret=1
					fi
				fi

				if [ "$ret" -eq 0 ]; then
					echo '{"success": true}'
				else
					echo '{"success": false}'
				fi
			;;
			upgrade)
				# Read the JSON object provided for the arguments
				read -r input

				json_load "${input}"

				json_get_var path path
				json_get_var auto_activate auto_activate
				json_get_var bank bank
				json_get_var keep_settings keep_settings

				ret=0

				# Do we have all the arguments we want?
				[ -z "${path}" ] || [ -z "${auto_activate}" ] || [ -z "${bank}" ] && ret=1
				# Sanity: is the given bankid really the one to be upgraded?
				[ "${bank}" -eq "$(iopsys_get_next_bank_id)" ] || ret=1

				# Does the given file actually exist?
				[ -r "${path}" ] || ret=1

				# Is the auto_activate provided in the JSON a boolean?
				# (meaning: here we should get 0 or 1 instead of any other string)
				[ "${auto_activate}" == "0" -o "${auto_activate}" == "1" ] || ret=1

				# Fail if any of the above sanity checks fail.
				[ ${ret} -eq 1 ] && {
					echo "{ \"result\": \"failure\" }"
					exit 0
				}

				# Set the default value for keep_settings
				keep_settings=${keep_settings:-1}

				# This ubus call does not reboot the system at any one time.
				# Although, the newly upgraded bank is activated by default.
				# Thus, pass "--no-reboot" if the bank is to be activated,
				# "--no-activate" otherwise.
				sysupgrade_flag=""
				if [ "${auto_activate}" -eq 1 ]; then
					sysupgrade_flag="--no-reboot"
				else
					sysupgrade_flag="--no-activate"
				fi

				# Set the flag to do not save configuration over reflash
				if [ "${keep_settings}" -eq 0 ]; then
					sysupgrade_flag="${sysupgrade_flag} -n"
				fi

				# Call sysupgrade synchonously. It should not time out the ubus call,
				# as it will just verify the image and do an ubus call, leading to
				# do_stage2 doing the actual upgrade.
				sysupgrade_result=""
				sysupgrade $sysupgrade_flag "$path" > /dev/null 2>&1
				if [ $? -eq 0 ]; then
					sysupgrade_result="ok"
				else
					sysupgrade_result="failure"
				fi

				echo "{ \"result\": \"$sysupgrade_result\" }"
			;;
		esac
	;;
esac
