#!/bin/bash

INTERACTIVE=True
ASK_TO_REBOOT=0
CONFIG=/boot/config.txt

USER=${SUDO_USER:-$(who -m | awk '{ print $1 }')}
if [ -z "$USER" ] && [ -n "$HOME" ]; then
  USER=$(getent passwd | awk -F: "\$6 == \"$HOME\" {print \$1}")
fi
if [ -z "$USER" ] || [ "$USER" = "root" ]; then
  USER=$(getent passwd | awk -F: '$3 == "1000" {print $1}')
fi

get_rdk_type_string() {
  if [ -f /sys/class/boardinfo/board_name ];then
    cat /sys/class/boardinfo/board_name
  fi

  if [ -f /sys/class/boardinfo/adc_boardid ];then
    board_id=$(cat /sys/class/boardinfo/adc_boardid)
  elif [ -f /sys/class/boardinf/adc_boardid ];then
    board_id=$(cat /sys/class/boardinf/adc_boardid)
  fi
  board_type=$(($board_id & 0xfff))
  hex_btype=$(printf "0x%x" $board_type)

  case $hex_btype in
  "0x301")
    echo "x5_rdk"
    ;;
  "0x302")
    echo "x5_rdk"
    ;;
  "0x210")
    echo "s600_rdk"
    ;;
  "0x110")
    echo "s600_rdk"
    ;;
  "0x310")
    echo "s600_rdk"
    ;;

  *)
    echo "null"
    exit 1
  ;;
  esac

}

is_installed() {
  if [ "$(dpkg -l "$1" 2> /dev/null | tail -n 1 | cut -d ' ' -f 1)" != "ii" ]; then
    return 1
  else
    return 0
  fi
}

calc_wt_size() {
  # NOTE: it's tempting to redirect stderr to /dev/null, so supress error
  # output from tput. However in this case, tput detects neither stdout or
  # stderr is a tty and so only gives default 80, 24 values
  WT_HEIGHT=18
  WT_WIDTH=$(tput cols)

  if [ -z "$WT_WIDTH" ] || [ "$WT_WIDTH" -lt 60 ]; then
    WT_WIDTH=80
  fi
  if [ "$WT_WIDTH" -gt 178 ]; then
    WT_WIDTH=120
  fi
  WT_MENU_HEIGHT=$((WT_HEIGHT - 7))
}

do_about() {
  whiptail --msgbox "\
This tool provides a straightforward way of doing initial
configuration of the RDK. Although it can be run
at any time, some of the options may have difficulties if
you have heavily customised your installation.\
" 20 70 1
  return 0
}

do_change_pass() {
  whiptail --msgbox "You will now be asked to enter a new password for the $USER user" 20 60 1
  passwd "$USER" &&
  whiptail --msgbox "Password changed successfully" 20 60 1
}

set_config_var() {
  lua - "$1" "$2" "$3" <<EOF > "$3.bak"
local key=assert(arg[1])
local value=assert(arg[2])
local fn=assert(arg[3])
local file=assert(io.open(fn))
local made_change=false
for line in file:lines() do
  if line:match("^#?%s*"..key.."=.*$") then
    line=key.."="..value
    made_change=true
  end
  print(line)
end

if not made_change then
  print(key.."="..value)
end
EOF
mv "$3.bak" "$3"
}

clear_config_var() {
  lua - "$1" "$2" <<EOF > "$2.bak"
local key=assert(arg[1])
local fn=assert(arg[2])
local file=assert(io.open(fn))
for line in file:lines() do
  if line:match("^%s*"..key.."=.*$") then
    line="#"..line
  end
  print(line)
end
EOF
mv "$2.bak" "$2"
}

get_config_var() {
  lua - "$1" "$2" <<EOF
local key=assert(arg[1])
local fn=assert(arg[2])
local file=assert(io.open(fn))
local found=false
for line in file:lines() do
  local val = line:match("^%s*"..key.."=(.*)$")
  if (val ~= nil) then
    print(val)
    found=true
    break
  end
end
if not found then
   print(0)
end
EOF
}

is_uname_current() {
  test -d "/lib/modules/$(uname -r)"
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_change_locale() {
  if [ "$INTERACTIVE" = True ]; then
    if dpkg-reconfigure locales; then
      ASK_TO_REBOOT=1
    fi
    whiptail --yesno "Would you like to install language-pack by apt?\n\
Note1: Chaning locale without installing language-pack may result in incomplete language switching.\n\
Note2: language-pack only needs to be installed ONCE." --defaultno "$WT_HEIGHT" "$WT_WIDTH" 2
    RES=$?
  else
    if ! LOCALE_LINE="$(grep -E "^$1( |$)" /usr/share/i18n/SUPPORTED)"; then
      return 1
    fi
    export LC_ALL=C
    export LANG=C
    LG="/etc/locale.gen"
    NEW_LANG="$(echo "$LOCALE_LINE" | cut -f1 -d " ")"
    [ -L "$LG" ] && [ "$(readlink $LG)" = "/usr/share/i18n/SUPPORTED" ] && rm -f "$LG"
    echo "$LOCALE_LINE" > /etc/locale.gen
    update-locale --no-checks LANG
    update-locale --no-checks "LANG=$NEW_LANG"
    dpkg-reconfigure -f noninteractive locales
    RES=0
  fi
  if [ "$RES" = "0" ] && [ -e /etc/default/locale ];then
    default_lang=$(cat /etc/default/locale)
    lang_code=${default_lang%%_*}
    lang_code=${lang_code##*=}

    sudo apt update && sudo apt install -y language-pack-"${lang_code}"* language-pack-gnome-"${lang_code}"*
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_change_timezone() {
  if [ "$INTERACTIVE" = True ]; then
    dpkg-reconfigure tzdata
  else
    TIMEZONE="$1"
    if [ ! -f "/usr/share/zoneinfo/$TIMEZONE" ]; then
      return 1;
    fi
    rm /etc/localtime
    echo "$TIMEZONE" > /etc/timezone
    dpkg-reconfigure -f noninteractive tzdata 2> /dev/null
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_configure_keyboard() {
  printf "Reloading keymap. This may take a short while\n"
  rm -f /etc/console-setup/cached_*
  if [ "$INTERACTIVE" = True ]; then
    dpkg-reconfigure keyboard-configuration
  else
    KEYMAP="$1"
    sed -i /etc/default/keyboard -e "s/^XKBLAYOUT.*/XKBLAYOUT=\"$KEYMAP\"/"
    dpkg-reconfigure -f noninteractive keyboard-configuration
  fi
  if [ "$INIT" = "systemd" ]; then
    systemctl restart keyboard-setup
  fi
  setsid sh -c 'exec setupcon --save -k --force <> /dev/tty1 >&0 2>&1'
  udevadm trigger --subsystem-match=input --action=change
  return 0
}

get_hostname() {
  tr -d " \t\n\r" < /etc/hostname
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_hostname() {
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "\
Please note: RFCs mandate that a hostname's labels \
may contain only the ASCII letters 'a' through 'z' (case-insensitive),
the digits '0' through '9', and the hyphen.
Hostname labels cannot begin or end with a hyphen.
No other symbols, punctuation characters, or blank spaces are permitted.\
" 20 70 1
  fi
  CURRENT_HOSTNAME=$(get_hostname)
  if [ "$INTERACTIVE" = True ]; then
    NEW_HOSTNAME=$(whiptail --inputbox "Please enter a hostname" 20 60 "$CURRENT_HOSTNAME" 3>&1 1>&2 2>&3)
  else
    NEW_HOSTNAME="$1"
  fi
  if [[ -n "$NEW_HOSTNAME" ]] && [[ "$NEW_HOSTNAME" != "$CURRENT_HOSTNAME" ]]; then
    if [ "$INIT" = "systemd" ] && systemctl -q is-active dbus && ! ischroot; then
      hostnamectl set-hostname "$NEW_HOSTNAME" 2> /dev/null
    else
      echo "$NEW_HOSTNAME" > /etc/hostname
    fi
    sed -i "s/127\.0\.1\.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts
    ASK_TO_REBOOT=1
  fi
}

list_wlan_interfaces() {
  for dir in /sys/class/net/*/wireless; do
    if [ -d "$dir" ]; then
      IFACE="$(basename "$(dirname "$dir")")"
      if wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
        echo "$IFACE"
      fi
    fi
  done
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_wifi_ssid_passphrase() {
  RET=0

  if systemctl -q is-active dhcpcd; then
    IFACE="$(list_wlan_interfaces | head -n 1)"

    if [ -z "$IFACE" ]; then
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "No wireless interface found" 20 60
      fi
      return 1
    fi

    if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60
      fi
      return 1
    fi
  elif ! systemctl -q is-active NetworkManager; then
    if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "No supported network connection manager found" 20 60
      fi
      return 1
  fi

  SSID="$1"
  while [ -z "$SSID" ] && [ "$INTERACTIVE" = True ]; do
    if ! SSID=$(whiptail --inputbox "Please enter SSID" 20 60 3>&1 1>&2 2>&3); then
      return 0
    elif [ -z "$SSID" ]; then
      whiptail --msgbox "SSID cannot be empty. Please try again." 20 60
    fi
  done

  PASSPHRASE="$2"
  while [ "$INTERACTIVE" = True ]; do
    if ! PASSPHRASE=$(whiptail --passwordbox "Please enter passphrase. Leave it empty if none." 20 60 3>&1 1>&2 2>&3); then
      return 0
    else
      break
    fi
  done

  # Escape special characters for embedding in regex below
  ssid="$(echo "$SSID" \
   | sed 's;\\;\\\\;g' \
   | sed -e 's;\.;\\\.;g' \
         -e 's;\*;\\\*;g' \
         -e 's;\+;\\\+;g' \
         -e 's;\?;\\\?;g' \
         -e 's;\^;\\\^;g' \
         -e 's;\$;\\\$;g' \
         -e 's;\/;\\\/;g' \
         -e 's;\[;\\\[;g' \
         -e 's;\];\\\];g' \
         -e 's;{;\\{;g'   \
         -e 's;};\\};g'   \
         -e 's;(;\\(;g'   \
         -e 's;);\\);g'   \
         -e 's;";\\\\\";g')"

  HIDDEN=${3:-0}
  PLAIN=${4:-1}

  if systemctl -q is-active dhcpcd; then
    wpa_cli -i "$IFACE" list_networks \
     | tail -n +2 | cut -f -2 | grep -P "\t$ssid$" | cut -f1 \
     | while read -r ID; do
      wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
    done

    ID="$(wpa_cli -i "$IFACE" add_network)"
    wpa_cli -i "$IFACE" set_network "$ID" ssid "\"$SSID\"" 2>&1 | grep -q "OK"
    RET=$((RET + $?))

    if [ -z "$PASSPHRASE" ]; then
      wpa_cli -i "$IFACE" set_network "$ID" key_mgmt NONE 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    else
      if [ "$PLAIN" = 1 ]; then
        PASSPHRASE="\"$PASSPHRASE\""
      fi
      wpa_cli -i "$IFACE" set_network "$ID" psk "$PASSPHRASE" 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    fi
    if [ "$HIDDEN" -ne 0 ]; then
      wpa_cli -i "$IFACE" set_network "$ID" scan_ssid 1 2>&1 | grep -q "OK"
      RET=$((RET + $?))
    fi
    if [ $RET -eq 0 ]; then
      wpa_cli -i "$IFACE" enable_network "$ID" > /dev/null 2>&1
    else
      wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1
      if [ "$INTERACTIVE" = True ]; then
        whiptail --msgbox "Failed to set SSID or passphrase" 20 60
      fi
    fi
    wpa_cli -i "$IFACE" save_config > /dev/null 2>&1
    echo "$IFACE_LIST" | while read -r IFACE; do
      wpa_cli -i "$IFACE" reconfigure > /dev/null 2>&1
    done
  else
    if [ "$HIDDEN" -ne 0 ]; then
      nmcli device wifi connect "$SSID"  password "$PASSPHRASE" hidden true | grep -q "activated"
    else
      nmcli device wifi connect "$SSID"  password "$PASSPHRASE" | grep -q "activated"
    fi
    RET=$((RET + $?))
  fi

  return "$RET"
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_boot_behaviour() {
  if [ "$INTERACTIVE" = True ]; then
    BOOTOPT=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Boot Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  \
      "B1 Console" "Text console, requiring user to login" \
      "B2 Console Autologin" "Text console, automatically logged in as '$USER' user" \
      "B3 Desktop" "Desktop GUI, requiring user to login" \
      "B4 Desktop Autologin" "Desktop GUI, automatically logged in as '$USER' user" \
      3>&1 1>&2 2>&3)
  else
    BOOTOPT=$1
  fi
  if [ -n "$BOOTOPT" ]; then
    case "$BOOTOPT" in # Handle default target
      B1*|B2*) # Console
        systemctl --quiet set-default multi-user.target
        ;;
      B3*|B4*) # Desktop
        if [ -e /etc/init.d/lightdm ] || [ "$(systemctl is-active gdm)" = "active" ] ; then
          systemctl --quiet set-default graphical.target
        else
          whiptail --msgbox "Do 'sudo apt-get install lightdm' or 'sudo apt-get install gdm3' to allow configuration of boot to desktop" 20 60 2
          return 1
        fi
        ;;
      *)
        whiptail --msgbox "Programmer error, unrecognised boot option" 20 60 2
        return 1
        ;;
    esac
    case "$BOOTOPT" in # Handle autologin
      B1*|B3*) # Autologin disabled
        if [ -z "${BOOTOPT%%B3*}" ]; then
          if [ "$(systemctl is-active gdm)" = "active" ];then
            sed /etc/gdm3/custom.conf -i -e 's/^AutomaticLoginEnable =.*/AutomaticLoginEnable = false/'
            sed /etc/gdm3/custom.conf -i -e 's/^AutomaticLogin =.*/# AutomaticLogin = sunrise/'
          else
            # lightdm
            sed /etc/lightdm/lightdm.conf.d/22-hobot-autologin.conf -i -e "s/^autologin-user=.*/#autologin-user=/"
          fi
        fi
        # shellcheck disable=SC2016
        rm -f /etc/systemd/system/serial-getty@ttyS0.service.d/autologin.conf
        rm -f /etc/pam.d/serial-getty
        ;;
      B2*|B4*) # Autologin enabled
        if [ -z "${BOOTOPT%%B4*}" ]; then
          if [ "$(systemctl is-active gdm)" = "active" ];then
            sed /etc/gdm3/custom.conf -i -e 's/^AutomaticLoginEnable =.*/AutomaticLoginEnable = true/'
            sed /etc/gdm3/custom.conf -i -e 's/^# AutomaticLogin =.*/AutomaticLogin = sunrise/'
          else
            sed /etc/lightdm/lightdm.conf.d/22-hobot-autologin.conf -i -e "s/^\(#\|\)autologin-user=.*/autologin-user=$USER/"
            fi
        fi
        mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d

        cat > /etc/systemd/system/serial-getty@ttyS0.service.d/autologin.conf <<EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin sunrise --noclear %I \$TERM
PAMName=serial-getty
EOF
        cat > /etc/pam.d/serial-getty <<EOF
auth sufficient pam_permit.so
account sufficient pam_permit.so
session sufficient pam_permit.so
EOF
        ;;
    esac
    if [ "$INIT" = "systemd" ]; then
      systemctl daemon-reload
      systemctl restart serial-getty@ttyS0.service
    fi
    ASK_TO_REBOOT=1
  fi
}


do_fb_console_resolution() {
  if [ "$INTERACTIVE" = True ]; then
    output=$(get_hdmi_res)
    height=$(echo "$output" | cut -d',' -f1)
    width=$(echo "$output" | cut -d',' -f2)
    default_resolution="${width}x${height}"

    modes_file="/sys/class/graphics/fb0/modes"
    options=()
    original_lines=()
    default_option_index=-1

    while read -r line; do
      resolution=$(echo "$line" | cut -d ':' -f 2)
      # shellcheck disable=SC2001
      if [ "$(echo "$resolution" | sed 's/p-[0-9]\+$//')" = "$default_resolution" ]; then
        default_option_index=${#options[@]}
      fi

      options+=("$resolution" "")
      original_lines+=("$line" "")
    done < "$modes_file"

    chosen_resolution=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item \
      "${options[$default_option_index]}" --menu "Set FB Console Resolution" "$WT_HEIGHT" "$WT_WIDTH"  \
      "$WT_MENU_HEIGHT"  "${options[@]}" --cancel-button Back --ok-button Select 3>&1 1>&2 2>&3)
    RET=$?
  else
    chosen_resolution=$1
    RET=0
  fi
    if [ $RET -eq 1 ]; then
      return 0
    elif [ $RET -eq 0 ]; then
      for ((i=0; i<${#options[@]}; i++)); do
        if [ "${options[$i]}" = "$chosen_resolution" ]; then
          chosen_resolution="${original_lines[$i]}"
          break
        fi
      done

      echo "$chosen_resolution" > /sys/class/graphics/fb0/mode

      read -r -t 10 -p "Please enter 'yes' in 10 seconds to confirm your selection:   " confirm
      if [ "$confirm" = "yes" ]; then
        whiptail --msgbox "Your resolution has been changed:  $chosen_resolution" "$WT_HEIGHT" "$WT_WIDTH"
        # shellcheck disable=SC2001
        set_config_var fb_console_width "$(echo "$chosen_resolution" | sed 's/.*:\([0-9]\+\)x\([0-9]\+\).*/\1/')" ${CONFIG}
        # shellcheck disable=SC2001
        set_config_var fb_console_height "$(echo "$chosen_resolution" | sed 's/.*:\([0-9]\+\)x\([0-9]\+\).*/\2/')" ${CONFIG}
        # shellcheck disable=SC2001
        set_config_var fb_console_refresh_rate "$(echo "$chosen_resolution" | sed 's/.*-//')" ${CONFIG}
      else
        #fall back
        echo "${original_lines[$default_option_index]}" > /sys/class/graphics/fb0/mode
        whiptail --msgbox "Your resolution is restored" "$WT_HEIGHT" "$WT_WIDTH"

      fi
      if [ "$INTERACTIVE" = True ]; then
        ASK_TO_REBOOT=1
      fi
    fi
}

get_leds () {
  if [ ! -e /sys/class/leds/ACT/trigger ] ; then
    echo -1
  elif grep -q "\\[heartbeat\\]" /sys/class/leds/ACT/trigger ; then
    echo 0
  elif grep -q "\\[default-on\\]" /sys/class/leds/ACT/trigger ; then
    echo 1
  else
    echo -1
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_leds() {
  CURRENT=$(get_leds)
  if [ "$CURRENT" -eq -1 ] ; then
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The LED behaviour cannot be changed on this model of RDK" 20 60 1
    fi
    return 1
  fi
  DEFAULT=--defaultno
  if [ "$CURRENT" -eq 0 ]; then
    DEFAULT=
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Would you like the power LED to flash with heartbeat?" $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ "$RET" -eq 0 ]; then
    LEDSET="heartbeat"
    STATUS="flash with heartbeat"
  elif [ "$RET" -eq 1 ]; then
    LEDSET="default-on"
    STATUS="be on constantly"
  else
    return "$RET"
  fi
  sed $CONFIG -i -e "s/dtparam=act_led_trigger=.*/dtparam=act_led_trigger=$LEDSET/"
  if ! grep -q "dtparam=act_led_trigger" $CONFIG ; then
    sed $CONFIG -i -e "\$adtparam=act_led_trigger=$LEDSET"
  fi
  echo $LEDSET | tee /sys/class/leds/ACT/trigger > /dev/null
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The power LED will $STATUS" 20 60 1
  fi
}


get_browser() {
  update-alternatives --display x-www-browser | grep currently | cut -d " " -f 7 | cut -d / -f 4
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_browser() {
  if [ "$INTERACTIVE" = True ]; then
    RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select Browser" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  \
      "1" "Chromium" \
      "2" "Firefox" \
      3>&1 1>&2 2>&3)
  else
    RES=""
    BROWSER=$1
  fi
  if [ "$RES" = "1" ] ; then
    # Chromium may be provided by snap as /snap/bin/chromium or by apt as chromium-browser.
    if command -v chromium >/dev/null 2>&1 || command -v chromium-browser >/dev/null 2>&1 || \
      is_installed chromium-browser || is_installed chromium; then
      BROWSER="chromium"
      BSTRING="Chromium"
    else
      apt update
      if apt-get install -y chromium-browser || apt-get install -y chromium; then
        BROWSER="chromium"
        BSTRING="Chromium"
      fi
    fi
  elif [ "$RES" = "2" ] ; then
    BROWSER="firefox"
    BSTRING="Firefox"
  fi
  # Resolve the browser executable and desktop entry used by the selected browser.
  # Chromium needs special handling because Ubuntu noble may install it as a snap.
  if [ "$BROWSER" = "chromium" ]; then
    BROWSER_BIN="$(command -v chromium || command -v chromium-browser || true)"
    BROWSER_DESKTOP="chromium_chromium.desktop"

    if [ "$BROWSER_BIN" = "/snap/bin/chromium" ]; then
      BROWSER_BIN="/usr/local/bin/chromium-x-www-browser"
      cat > "$BROWSER_BIN" <<'EOF'
#!/bin/sh
exec /snap/bin/chromium "$@"
EOF
      chmod +x "$BROWSER_BIN"
    fi
  else
    BROWSER_BIN="/usr/bin/$BROWSER"
    BROWSER_DESKTOP="$BROWSER.desktop"
  fi

  # Register the resolved executable before selecting it. This avoids failures
  # when the browser path was not already known to update-alternatives.
  update-alternatives --install /usr/bin/x-www-browser x-www-browser "$BROWSER_BIN" 100
  update-alternatives --set x-www-browser "$BROWSER_BIN" > /dev/null

  # x-www-browser controls command-line browser launch, while xdg controls
  # desktop URL handling. Keep both layers pointing at the same browser.
  if [ -z "$2" ] ; then
    sudo -u "$USER" xdg-settings set default-web-browser "$BROWSER_DESKTOP"
    sudo -u "$USER" xdg-mime default "$BROWSER_DESKTOP" x-scheme-handler/http
    sudo -u "$USER" xdg-mime default "$BROWSER_DESKTOP" x-scheme-handler/https
  else
    sudo -u "$2" xdg-settings set default-web-browser "$BROWSER_DESKTOP"
    sudo -u "$2" xdg-mime default "$BROWSER_DESKTOP" x-scheme-handler/http
    sudo -u "$2" xdg-mime default "$BROWSER_DESKTOP" x-scheme-handler/https
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Default browser set to $BSTRING" 20 60 1
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_drm_display_chose() {
  if [ "$INTERACTIVE" = True ]; then
    if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
        whiptail --msgbox "RDK S100 ONLY supports HDMI Display!"  20 60 1
        RES=2
    else
      RES=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Select DRM Display" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  \
        "1" "DSI" \
        "2" "HDMI" \
        3>&1 1>&2 2>&3)
    fi
  else
    RES=""
    BSTRING=$1
  fi

  if [ "$RES" = "1" ] ; then
    if [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf ]; then
        mv /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable
    fi
    if [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable ]; then
        mv /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf
    fi
    BSTRING="DSI"
  elif [ "$RES" = "2" ] ; then
    if [ -e /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf ]; then
        mv /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf /etc/X11/xorg.conf.d/xorg_hdmi_ignore.conf.disable
    fi
    if [ -e /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable ]; then
        mv /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf.disable /etc/X11/xorg.conf.d/xorg_dsi_ignore.conf
    fi
    BSTRING="HDMI"
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Default display set to $BSTRING" 20 60 1
  fi
}

do_update_miniboot()
{
  DEFAULT=--defaultno
  if [ "$INTERACTIVE" = True ]; then
    if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
      FLASH_TYPE="NOR"
    else
      FLASH_TYPE="NAND"
    fi
    if whiptail --yesno "Would you like update the minimal boot image in $FLASH_TYPE flash?\n\nCaution: Abnormal interruptions are not allowed during the upgrade process!" $DEFAULT 20 60 2; then
      if is_installed hobot-miniboot || apt update || apt-get install -y hobot-miniboot; then
        rdk-miniboot-update --reboot n
        ASK_TO_REBOOT=1
      fi
    fi
  fi
}

get_vnc_resolution() {
  if [ -e /etc/xdg/autostart/vnc_xrandr.desktop ] ; then
    grep fb /etc/xdg/autostart/vnc_xrandr.desktop | cut -f 15 -d ' '
  else
    echo ""
  fi
}

do_vnc_resolution() {
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_vnc_resolution)
    if [ "$CUR" = "" ] ; then
      CUR=640x480
    fi
    FUN="$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "$CUR" --menu "Set VNC Resolution" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "640x480" "" "720x480" "" "800x600" "" "1024x768" "" "1280x720" "" "1280x1024" "" "1600x1200" "" "1920x1080" "" 3>&1 1>&2 2>&3)"
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    cat > /etc/xdg/autostart/vnc_xrandr.desktop << EOF
[Desktop Entry]
Type=Application
Name=vnc_xrandr
Comment=Set resolution for VNC
NoDisplay=true
Exec=sh -c "if ! (xrandr | grep -q -w connected) ; then /usr/bin/xrandr --fb $FUN ; fi"
EOF
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The resolution is set to $FUN" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

get_ssh() {
  if service ssh status | grep -q inactive; then
    echo 1
  else
    echo 0
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_ssh() {
  if [ -e /var/log/regen_ssh_keys.log ] && ! grep -q "^finished" /var/log/regen_ssh_keys.log; then
    whiptail --msgbox "Initial ssh key generation still running. Please wait and try again." 20 60 2
    return 1
  fi
  DEFAULT=--defaultno
  if [ "$(get_ssh)" -eq 0 ]; then
    DEFAULT=
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno \
      "Would you like the SSH server to be enabled?\n\nCaution: Default and weak passwords are a security risk when SSH is enabled!" \
      $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ "$RET" -eq 0 ]; then
    ssh-keygen -A &&
    update-rc.d ssh enable &&
    invoke-rc.d ssh start &&
    STATUS=enabled
  elif [ "$RET" -eq 1 ]; then
    update-rc.d ssh disable &&
    invoke-rc.d ssh stop &&
    systemctl stop ssh.socket
    STATUS=disabled
  else
    return "$RET"
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The SSH server is $STATUS" 20 60 1
  fi
}

get_vnc() {
  if systemctl status x11vnc.service  | grep -q -w active; then
    echo 0
  else
    echo 1
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_vnc() {
  DEFAULT=--defaultno
  if [ "$(get_vnc)" -eq 0 ]; then
    DEFAULT=
  fi
  APT_GET_FLAGS=""
  if [ "$INTERACTIVE" = True ]; then
    if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
      whiptail --msgbox "VNC is not supported on S100, please use nomachine!"  20 60 1
      RET=1
    else
      whiptail --yesno "Would you like the VNC Server to be enabled?" $DEFAULT 20 60 2
      RET=$?
    fi
  else
    RET=$1
    APT_GET_FLAGS="-y"
  fi
  if [ "$RET" -eq 0 ]; then
    if is_installed x11vnc; then
      systemctl disable x11vnc.service
      systemctl stop x11vnc.service
    fi

    if is_installed x11vnc || apt-get install "$APT_GET_FLAGS" x11vnc; then
      whiptail --msgbox "You will now be asked to enter a password for the VNC server" 20 60 1
      mkdir -p /etc/.vnc
      vncpasswd /etc/.vnc/passwd &&
      whiptail --msgbox "Password setted successfully" 20 60 1
      systemctl enable x11vnc.service &&
      systemctl start x11vnc.service &&
      STATUS=enabled
    else
      return 1
    fi
  elif [ "$RET" -eq 1 ]; then
    if is_installed x11vnc; then
      systemctl disable x11vnc.service
      systemctl stop x11vnc.service
    fi
    STATUS=disabled
  else
    return "$RET"
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The VNC Server is $STATUS" 20 60 1
  fi
}

warn_box() {
  text="$1"
  return "$(whiptail --title "WARNNING" --msgbox "$text" 20 60 1)"
}

parse_peri_key() {
  local raw_key=$1

  raw_key=$(echo "$raw_key" | tr -d '[:space:]')
  if [ -z "$raw_key" ]; then
    return 1
  fi

  if [[ "$raw_key" == *=* ]]; then
    PARSED_PERI_ALIAS=${raw_key%%=*}
    PARSED_PERI_NODE=${raw_key#*=}
  else
    PARSED_PERI_ALIAS=$raw_key
    PARSED_PERI_NODE=$raw_key
  fi

  if [ -z "$PARSED_PERI_ALIAS" ] || [ -z "$PARSED_PERI_NODE" ]; then
    return 1
  fi

  return 0
}

resolve_peri_node_key() {
  local key=$1

  if [ -n "${peri_alias_to_node[$key]}" ]; then
    echo "${peri_alias_to_node[$key]}"
  else
    echo "$key"
  fi
}

display_name_for_peri() {
  local key=$1

  if [ -n "${peri_node_to_alias[$key]}" ]; then
    echo "${peri_node_to_alias[$key]}"
  else
    echo "$key"
  fi
}

resolve_fdt_node() {
  local dtb_name=$1
  local node_key=$2
  local node_path=

  if [ -z "$node_key" ]; then
    return 1
  fi

  if [[ "$node_key" == /* ]]; then
    echo "$node_key"
    return 0
  fi

  node_path=$(fdtget "${dtb_name}" /__symbols__ "${node_key}" 2> /dev/null)
  if [ -n "$node_path" ]; then
    echo "$node_path"
    return 0
  fi

  return 1
}

update_status() {
  local dtb_name=$1
  local options=()
  local confstate=
  local node_path=
  local node_key=
  for peri in "${!peri_status[@]}"
  do
    node_key=$(resolve_peri_node_key "${peri}")
    node_path=$(resolve_fdt_node "${dtb_name}" "${node_key}")
    status=
    if [ -n "$node_path" ]; then
      status=$(fdtget -t s "${dtb_name}" "${node_path}" status 2> /dev/null)
    fi
    if [ ! -z "$status" ];then
      peri_status[${peri}]="$status"
    fi
    options+=("$peri" "                     ${peri_status[$peri]}")
  done
  peri_select=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
    --menu "Peripherals bus config" \
    "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  \
    --cancel-button Back \
    --ok-button Select \
    "${options[@]}" \
    3>&1 1>&2 2>&3)
  ret=$?
  if [ $ret -ne 0 ];then
    return 1
  fi
  unset options
  # echo peri_select=$peri_select
  # echo peri_status=${peri_status[$peri_select]}
  peri_ops "${dtb_name}" "$peri_select" "${peri_status[$peri_select]}"
  ret=$?
  if [ $ret -eq "0" ];then
    if [ "${peri_status[$peri_select]}" == "okay" ];then
      confstate="disabled"
    elif [ "${peri_status[$peri_select]}" == "disabled" ];then
      confstate="okay"
    else
      warn_box "undefined fdt node status !"
    fi
    apply_status "${dtb_name}" "${peri_select}" "${confstate}"
    ret=$?
    if [ $ret -ne "0" ];then
      warn_box "fdtput get some err: ${options[*]} ${peri_select} !"
    fi
    unset confstate
  fi
}

apply_status() {
  local dtb_name=$1
  local peri=$2
  local status=$3
  local array=${conf_peris[$peri]}
  local confstate="disabled"
  local peri_node=
  local peri_node_key=
  local cp_node=
  local cp_node_key=
  array=${array//,/ }
  if [ "${status}" == "okay" ];then
    confstate="disabled"
  elif [ "${status}" == "disabled" ];then
    :
  else
    warn_box "undefined fdt node status !"
  fi
  for cp in "${array[@]}"
  do
    cp_node_key=$(resolve_peri_node_key "${cp}")
    cp_node=$(resolve_fdt_node "${dtb_name}" "${cp_node_key}")
    if [ -n "$cp_node" ]; then
      fdtput -t s "${dtb_name}" "${cp_node}" status "${confstate}" 2> /dev/null
    fi
  done
  apply_state="true"
  peri_node_key=$(resolve_peri_node_key "${peri}")
  peri_node=$(resolve_fdt_node "${dtb_name}" "${peri_node_key}")
  if [ -z "$peri_node" ]; then
    return 1
  fi

  fdtput -t s "${dtb_name}" "${peri_node}" status "${status}" 2> /dev/null
  return $?
}

peri_ops() {
  local dtb_name=$1
  local peri=$2
  local status=$3
  local options=()
  local string=()
  local somep="false"
  local peris=
  local cperis=
  local cperi_display=
  if [ "${status}" == "okay" ];then
    options=("dis")
  else
    options=("en")
  fi
  if [ ! -z "${conf_peris[$peri]}" ];then
    peris=${conf_peris[$peri]}
    for cperi in ${peris//,/ }
    do
      cperi_display=$(display_name_for_peri "$cperi")
      if [ "${peri_status[$cperi_display]}" == "okay" ];then
        somep="true"
        cperis="${cperis} ${cperi_display}"
      fi
    done
    if [ "${somep}" == "true" ];then
      string=("Doing this and the ${cperis[@]} will be disabled")
    else
      string=("")
    fi
  else
    string=("")
  fi
  whiptail --title "Your select" \
    --yesno "Are you sure want to ${options[*]}able $peri? \
    \n${string[*]}" \
    20 60 \
    3>&1 1>&2 2>&3
  ret=$?
  if [ $ret -eq 0 ];then
    for cperi in ${peris//,/ }
    do
      cperi_display=$(display_name_for_peri "$cperi")
      if [ "${peri_status[$cperi_display]}" == "okay" ];then
        apply_status "${dtb_name}" "$cperi_display" "disabled"
        ret=$?
        if [ $ret -ne "0" ];then
          warn_box "fdtput get some err: ${options[*]} $cperi_display !"
          return $ret
        fi
      fi
    done
  fi
  return $ret
}

do_peripheral() {
  if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
    whiptail --msgbox "Please Refer to: \nhttps://developer.d-robotics.cc/rdk_doc/rdk_s/System_configuration/config_txt \nfor runtime fdt manipulation!"  20 "$WT_WIDTH" 1
    return
  fi
  board_id=$(cat /sys/class/boardinfo/adc_boardid)
  board_type=$(($board_id & 0xfff))
  hex_btype=$(printf "0x%x" "$board_type")

  rootsource=$(findmnt -n -o SOURCE / | sed 's~\[.*\]~~')
  resolved_root=$(readlink -f "$rootsource" 2> /dev/null)
  if [ -n "$resolved_root" ]; then
    rootsource="$resolved_root"
  fi

  rootpartnum=$(printf '%s\n' "$rootsource" | sed -nE \
    -e 's#^/dev/mmcblk[0-9]+p([0-9]+)$#\1#p' \
    -e 's#^/dev/nvme[0-9]+n[0-9]+p([0-9]+)$#\1#p' \
    -e 's#^/dev/[a-z]+([0-9]+)$#\1#p')

  if ! [[ "$rootpartnum" =~ ^[0-9]+$ ]]; then
      echo "Cannot parse root partition number from source: $rootsource"
      exit 1
  fi

    bootdisk=
    if [[ "$rootsource" =~ ^(/dev/mmcblk[0-9]+)p[0-9]+$ ]]; then
      bootdisk="${BASH_REMATCH[1]}"
    elif [[ "$rootsource" =~ ^(/dev/nvme[0-9]+n[0-9]+)p[0-9]+$ ]]; then
      bootdisk="${BASH_REMATCH[1]}"
    elif [[ "$rootsource" =~ ^(/dev/[a-z]+)[0-9]+$ ]]; then
      bootdisk="${BASH_REMATCH[1]}"
    fi

    if [ -z "$bootdisk" ] || [ ! -b "$bootdisk" ]; then
      echo "Cannot detect boot disk from root source: $rootsource"
      exit 1
    fi

    part_sep=""
    if [[ "$bootdisk" =~ [0-9]$ ]]; then
      part_sep="p"
    fi

  if [ "$rootpartnum" -gt 2 ] && [ ! -d "/boot/hobot" ];then
      case $hex_btype in
       "0x301")
          config="/etc/hobot.conf/x5rdk.conf"
          ;;
       "0x302")
          config="/etc/hobot.conf/x5rdk.conf"
          ;;
       "0x210")
          config="/etc/hobot.conf/s600rdk.conf"
          ;;
       "0x110")
          config="/etc/hobot.conf/s600rdk.conf"
          ;;
        "0x310")
          config="/etc/hobot.conf/s600rdk.conf"
          ;;

      *)
          echo "Unsupport board type!!"
          exit 1
          ;;
      esac
        partnum=$(parted "$bootdisk" print -sm | awk -F ':' '$1 ~ /^[0-9]+$/ && $7 ~ /boot/ {print $1; exit}')
        partdev="${bootdisk}${part_sep}${partnum}"
      bootfile="/tmp/boot.img"

        if [ -z "$partnum" ] || [ ! -b "$partdev" ]; then
          echo "Cannot detect boot partition on $bootdisk"
          exit 1
        fi

      if ! dd if="${partdev}" of="${bootfile}" bs=1M count=10 > /dev/null || [[ ! -f "${bootfile}" ]];then
          echo "dd is failed or ${bootfile} is not exist!"
          exit 1
      fi
      dtb_name=$(hb_dtb_tool -i "${bootfile}" -b "${board_type}" -g|grep dtb_name |awk '{print $2}')
      if [[ -z "$dtb_name" ]];then
      echo "hb_dtb_tool get ${board_type} failed!"
      exit 1
      fi
      elif [ "$rootpartnum" -eq 1 ] || [ "$rootpartnum" -eq 2 ] || [ -d "/boot/hobot" ];then
        case $hex_btype in
        "0x301")
          config="/etc/hobot.conf/x5rdk.conf"
          dtb_name="x5-rdk.dtb"
          ;;
        "0x302")
          config="/etc/hobot.conf/x5rdk.conf"
          dtb_name="x5-rdk-v1p0.dtb"
          ;;
        "0x210")
          config="/etc/hobot.conf/s600rdk.conf"
          dtb_name="rdk-s600-mcb-v0p2.dtb"
          ;;
        "0x110")
          config="/etc/hobot.conf/s600rdk.conf"
          dtb_name="rdk-s600-mcb-v0p1.dtb"
          ;;
        "0x310")
          config="/etc/hobot.conf/s600rdk.conf"
          dtb_name="rdk-s600-mcb-v1p0.dtb"
          ;;

        *)
          echo "Unsupport board type!!"
          exit 1
          ;;
        esac
        if [ -f "/boot/hobot/${dtb_name}" ];then
          cp "/boot/hobot/${dtb_name}" ${dtb_name}
        else
          echo "Dtb file not exist!!"
          exit 1
        fi
  fi
  if [ -z "$dtb_name" ];then
      echo "No dtb file find!!"
      exit 1
  fi

  if [ ! -f "$config" ];then
    echo "file ${config} is not exist!"
    exit 1
  fi

  declare -A peri_status
  declare -A conf_peris
  declare -A peri_alias_to_node
  declare -A peri_node_to_alias

  apply_state="false"

    while IFS= read -r line; do
      [ -z "$line" ] && continue
      case "$line" in
        \#*) continue ;;
      esac

      IFS=':' read -ra arr <<< "$line"
      parse_peri_key "${arr[0]}" || continue
      peri_alias=${PARSED_PERI_ALIAS}
      peri_node_key=${PARSED_PERI_NODE}

      peri_status[$peri_alias]="unknown"
      conf_peris[$peri_alias]="${arr[1]}"
      peri_alias_to_node[$peri_alias]="$peri_node_key"
      if [ -z "${peri_node_to_alias[$peri_node_key]}" ]; then
        peri_node_to_alias[$peri_node_key]="$peri_alias"
      fi
    done < "$config"

  while true; do
      update_status "$dtb_name"
      ret=$?
      if [ $ret -ne 0 ];then
          break
      fi
  done

  if [ "$rootpartnum" -gt 2 ] && [ ! -d "/boot/hobot" ];then
      if [ "${apply_state}" == "true" ];then
          hb_dtb_tool -i "${bootfile}" -b ${board_type} -s "$dtb_name"
          ret=$?
          if [ $ret -ne 0 ];then
              echo "hb_dtb_tool -s is failed!"
              exit 1
          fi
          dd if="${bootfile}" of="${partdev}"  > /dev/null
          ret=$?
          if [ $ret -ne 0 ];then
              echo "dd is failed!"
              exit 1
          fi
          ASK_TO_REBOOT=1
          sync
      fi
  elif [ "$rootpartnum" -eq 1 ] || [ "$rootpartnum" -eq 2 ] || [ -d "/boot/hobot" ];then
      if [ "${apply_state}" == "true" ];then
          cp "${dtb_name}" /boot/hobot/"${dtb_name}"
          ASK_TO_REBOOT=1
      fi
  fi
  rm -rf "$dtb_name" "${bootfile}"
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_wifi_antenna()
{

  if [ "$INTERACTIVE" = True ]; then
    if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
      whiptail --msgbox "RDK S100 does NOT support wifi antenna configuration!"  20 "$WT_WIDTH" 1
      return
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "Onboard" --menu "Set VNC Resolution" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "Onboard" "" "External" ""  3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    if [ "${FUN}" = "Onboard" ]; then
      /bin/switch_antenna trace
      set_config_var antenna_option trace ${CONFIG}
    elif [ "${FUN}" = "External" ]; then
      /bin/switch_antenna cable
      set_config_var antenna_option cable ${CONFIG}
    fi

    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The Wi-Fi antenna is switch to ${FUN} antenna" 20 60 1
    fi
  fi
}

get_cpu_boost() {
  boost=$(tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/boost)
  if [ "${boost}" = "0" ]; then
    echo 0
  else
    echo 1
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_cpu_boost() {
  if [[ "$(get_rdk_type_string)" = *"S100"* ]];then
    whiptail --msgbox "CPU Overclocking on S100 is not supported."  20 "$WT_WIDTH" 1
    return
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "\
Enabling overclocking will increase CPU power consumption.
Please install a sufficient radiator(such as enlarging the
radiator, using a cooling fan) to avoid system instability
caused by excessive temperature.\
" 20 70 1
  fi

  DEFAULT=--defaultno
  if [ "$(get_cpu_boost)" -eq 0 ]; then
    DEFAULT=
  fi

  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno \
      "Would you like the CPU boost to be enabled?" \
      $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  if [ "$RET" -eq 0 ]; then
    set_config_var arm_boost 1 ${CONFIG}
    echo 1 > /sys/devices/system/cpu/cpufreq/boost
    STATUS=enabled
  elif [ "$RET" -eq 1 ]; then
    set_config_var arm_boost 0 ${CONFIG}
    echo 0 > /sys/devices/system/cpu/cpufreq/boost
    STATUS=disabled
  else
    return "$RET"
  fi
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The CPU boost is $STATUS" 20 60 1
  fi
}

get_cpu_governor() {
  if [ -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor ] ; then
    tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
  else
    echo ""
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_cpu_governor() {
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cpu_governor)
    if [ "$CUR" = "" ] ; then
      CUR=performance
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --default-item "$CUR" --menu "Set CPU governor" \
      "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "conservative" "" "ondemand" "" "userspace" "" "powersave" "" "performance" "" "schedutil" "" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    set_config_var governor "$FUN" "${CONFIG}"
    echo "$FUN" > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The cpu governor is set to $FUN" 20 60 1
    fi
  fi
}

get_cpu_frequency() {
  if [ -e /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq ] ; then
    tr -d " \t\n\r" < /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq
  else
    echo ""
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_cpu_frequency() {
  if [ "$(get_cpu_governor)" != "userspace" ]; then
    whiptail --msgbox "The cpu frequency can only be set when the governor is set to userspace" 20 60 2
    return 0
  fi
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cpu_frequency)
    if [ "$CUR" = "" ] ; then
      CUR=1200000
    fi

    # whiptail --menu needs pairs: tag description tag description ...
    freq_menu=()
    if [ -r /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies ]; then
      for f in $(tr -d '\t\n\r\0' < /sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies); do
        [ -n "$f" ] || continue
        freq_menu+=("$f" "")
      done
    fi
    if [ "$(get_cpu_boost)" -eq 1 ] && [ -r /sys/devices/system/cpu/cpufreq/policy0/scaling_boost_frequencies ]; then
      for f in $(tr -d '\t\n\r\0' < /sys/devices/system/cpu/cpufreq/policy0/scaling_boost_frequencies); do
        [ -n "$f" ] || continue
        freq_menu+=("$f" "[boost]")
      done
    fi
    if [ "${#freq_menu[@]}" -eq 0 ]; then
      whiptail --msgbox "No available CPU frequencies found." 20 60 1
      return 0
    fi

    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --default-item "$CUR" --menu "Set CPU frequency" \
      "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "${freq_menu[@]}" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    set_config_var frequency "$FUN" "${CONFIG}"
    echo "$FUN" > /sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The cpu frequency is set to $FUN" 20 60 1
    fi
  fi
}

do_cpu_frequency_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" \
      --menu "Configure CPU frequency" \
      "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "C1 CPU Boost" "Configure CPU overclocking" \
      "C2 CPU Governor" "Configure the CPU frequency governor mode" \
      "C3 CPU Frequency" "Configure the CPU to run at a fixed frequency (only Governor = userspace)" \
      3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      C1\ *) do_cpu_boost ;;
      C2\ *) do_cpu_governor ;;
      C3\ *) do_cpu_frequency ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

get_total_memory()
{
  total_mem=$(awk '/MemTotal/ {print $2}' /proc/meminfo)

  # Round to the nearest 1, 2, 4 or 8 multiple
  rounded_mem=$(( (total_mem + 512 * 1024) / (1024 * 1024) ))  # Convert to GB and round
  echo ${rounded_mem}
}

get_ion_cma_memory()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/ion_cma)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

get_cma_reserved_memory()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/cma_reserved)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

get_carveout_memory()
{
  ion_size=$(awk '/total size/ {print $5}' /sys/kernel/debug/ion/heaps/carveout)
  ion_size=$(( ion_size / (1024 * 1024) ))
  echo ${ion_size}"MB"
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_config_ion_memory()
{
  if [[ "$(get_rdk_type_string)" = *"S100_"* ]];then
    ion_size_opt=("256MB+512MB+512MB" "" "512MB+1024MB+1024MB" "" "1024MB+2048MB+2048MB" "" "1024MB+3840MB+3840MB" "")
  elif [[ "$(get_rdk_type_string)" = *"S100P_"* ]];then
    ion_size_opt=("256MB+512MB+512MB" "" "512MB+1024MB+1024MB" "" "1024MB+3840MB+3840MB" "" "5120MB+5120MB+5120MB" "")
  else
    ion_size_opt=("128MB+320MB+320MB" "" "192MB+384MB+384MB" "" "256MB+512MB+512MB" "" "320MB+640MB+640MB" "" "512MB+1024MB+1024MB" "")
  fi
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_ion_cma_memory)+$(get_cma_reserved_memory)+$(get_carveout_memory)
    if [ "$CUR" = "" ] ; then
      CUR=128MB+320MB+320MB
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "$CUR" --menu "Set VNC Resolution" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select  "${ion_size_opt[@]}" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    IFS='+' read -r ion_cma_size_mb ion_reserved_size_mb ion_carveout_size_mb <<< "$FUN"

    ion_cma_size_mb="${ion_cma_size_mb/MB/}"
    ion_cma_size_hex=$(printf "0x%x" "$((ion_cma_size_mb * 1024 * 1024))")

    ion_reserved_size_mb="${ion_reserved_size_mb/MB/}"
    ion_reserved_size_hex=$(printf "0x%x" "$((ion_reserved_size_mb * 1024 * 1024))")

    ion_carveout_size_mb="${ion_carveout_size_mb/MB/}"
    ion_carveout_size_hex=$(printf "0x%x" "$((ion_carveout_size_mb * 1024 * 1024))")

    if grep -q "ion=ion_cma_size=" "${CONFIG}" || grep -q "#ion=ion_cma_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_cma_size=\|#ion=ion_cma_size=\).*/ion=ion_cma_size=${ion_cma_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_cma_size=${ion_cma_size_hex}" >> "${CONFIG}"
    fi

    if grep -q "ion=ion_reserved_size=" "${CONFIG}" || grep -q "#ion=ion_reserved_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_reserved_size=\|#ion=ion_reserved_size=\).*/ion=ion_reserved_size=${ion_carveout_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_reserved_size=${ion_reserved_size_hex}" >> "${CONFIG}"
    fi

    if grep -q "ion=ion_carveout_size=" "${CONFIG}" || grep -q "#ion=ion_carveout_size=" "${CONFIG}"; then
      sed -i "s/\(ion=ion_carveout_size=\|#ion=ion_carveout_size=\).*/ion=ion_carveout_size=${ion_carveout_size_hex}/" "${CONFIG}"
    else
      echo "ion=ion_carveout_size=${ion_carveout_size_hex}" >> "${CONFIG}"
    fi
    if [ "$INTERACTIVE" = True ]; then
      whiptail --msgbox "The ion memory is set to ${FUN}" 20 60 1
      ASK_TO_REBOOT=1
    fi
  fi
}

do_expand_rootfs() {
  rm -f /etc/.do_expand_partiton /etc/.do_resizefs_rootfs
  /etc/init.d/hobot-resizefs start
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Root partition has been resized" 20 60 1
  fi
}

get_proxy() {
  SCHEME="$1"
  VAR_NAME="${SCHEME}_proxy"
  if [ -f /etc/profile.d/proxy.sh ]; then
    # shellcheck disable=SC1091
    . /etc/profile.d/proxy.sh
  fi
  eval "echo \$$VAR_NAME"
}

do_proxy() {
  SCHEMES="$1"
  ADDRESS="$2"
  if [ "$SCHEMES" = "all" ]; then
    CURRENT="$(get_proxy http)"
    SCHEMES="http https ftp rsync"
  else
    CURRENT="$(get_proxy "$SCHEMES")"
  fi
  if [ "$INTERACTIVE" = True ]; then
    if [ "$SCHEMES" = "no" ]; then
      STRING="Please enter a comma separated list of addresses that should be excluded from using proxy servers.\\nEg: localhost,127.0.0.1,localaddress,.localdomain.com"
    else
      STRING="Please enter proxy address.\\nEg: http://user:pass@proxy:8080"
    fi
    if ! ADDRESS="$(whiptail --inputbox "$STRING"  20 60 "$CURRENT" 3>&1 1>&2 2>&3)"; then
      return 0
    fi
  fi
  for SCHEME in $SCHEMES; do
    unset "${SCHEME}_proxy"
    CURRENT="$(get_proxy "$SCHEME")"
    if [ "$CURRENT" != "$ADDRESS" ]; then
      ASK_TO_REBOOT=1
    fi
    if [ -f /etc/profile.d/proxy.sh ]; then
      sed -i "/^export ${SCHEME}_/Id" /etc/profile.d/proxy.sh
    fi
    if [ "${SCHEME#*http}" != "$SCHEME" ]; then
      if [ -f /etc/apt/apt.conf.d/01proxy ]; then
        sed -i "/::${SCHEME}::Proxy/d" /etc/apt/apt.conf.d/01proxy
      fi
    fi
    if [ -z "$ADDRESS" ]; then
      STATUS=cleared
      continue
    fi
    STATUS=updated
    SCHEME_UPPER="$(echo "$SCHEME" | tr '[:lower:]' '[:upper:]')"
    echo "export ${SCHEME_UPPER}_PROXY=\"$ADDRESS\"" >> /etc/profile.d/proxy.sh
    if [ "$SCHEME" != "rsync" ]; then
      echo "export ${SCHEME}_proxy=\"$ADDRESS\"" >> /etc/profile.d/proxy.sh
    fi
    if [ "${SCHEME#*http}" != "$SCHEME" ]; then
      echo "Acquire::$SCHEME::Proxy \"$ADDRESS\";"  >> /etc/apt/apt.conf.d/01proxy
    fi
  done
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "Proxy settings $STATUS" 20 60 1
  fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_boot_order() {
  if [ "$INTERACTIVE" = True ]; then
    BOOTOPT=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Boot Device Order" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  \
      "B1 SD Card Boot" "Boot from SD Card if available, otherwise boot from USB" \
      "B2 EMMC Boot" "Boot from USB if available, otherwise boot from SD Card" \
      3>&1 1>&2 2>&3)
  else
    BOOTOPT=$1
    true
  fi
  case "$BOOTOPT" in
    B1*)
      parted /dev/mmcblk0 set 2 boot off
      STATUS="SD Card"
      ;;
    B2*)
      parted /dev/mmcblk0 set 2 boot on
      STATUS="EMMC"
      ;;
    *)
      whiptail --msgbox "Programmer error, unrecognised boot option" 20 60 2
      return 1
      ;;
  esac
  ASK_TO_REBOOT=1
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "$STATUS is default boot device" 20 60 1
  fi
}

do_update() {
  apt-get update &&
  apt-get install hobot-io &&
  printf "Sleeping 5 seconds before reloading srpi-config\n" &&
  sleep 5 &&
  exec srpi-config
}

nonint() {
  "$@"
}

# Needs to be run as root
if [ "$(id -u)" -ne 0 ]; then
  printf "Script must be run as root. Try 'sudo srpi-config'\n"
  exit 1
fi

#
# Command line options for non-interactive use
#
for i in "$@"
do
  case $i in
  --expand-rootfs)
    INTERACTIVE=False
    rm -f /etc/.do_expand_partiton /etc/.do_resizefs_rootfs
    /etc/init.d/hobot-resizefs start
    exit 0
    ;;
  nonint)
    INTERACTIVE=False
    "$@"
    exit $?
    ;;
  *)
    # unknown option
    ;;
  esac
done

do_system_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "System Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
    "S1 Wireless LAN" "Enter SSID and passphrase" \
    "S2 Password" "Change password for the '$USER' user" \
    "S3 Hostname" "Set name for this computer on a network" \
    "S4 Boot / Auto Login" "Select boot into desktop or to command line" \
    "S5 Power LED" "Set behaviour of power LED" \
    "S6 Browser" "Choose default web browser" \
    "S7 Update Miniboot" "Update the minimal boot image in flash" \
    3>&1 1>&2 2>&3)

  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      S1\ *) do_wifi_ssid_passphrase ;;
      S2\ *) do_change_pass ;;
      S3\ *) do_hostname ;;
      S4\ *) do_boot_behaviour ;;
      S5\ *) do_leds ;;
      S6\ *) do_browser ;;
      S7\ *) do_update_miniboot ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_display_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Display Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
    "D1 Dsiplay Chose" " DSI or HDMI" \
    3>&1 1>&2 2>&3)

  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      D1\ *) do_drm_display_chose ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

get_cur_audio_hat(){
  if [ -f /etc/hobot_audio_config/cur_audio_hat ]; then
    cat /etc/hobot_audio_config/cur_audio_hat
  else
    echo "Audio Driver HAT V1"
  fi
}

BOARD_MEMORY_SIZE=0
getMemorySize()
{
    if [ -f "/sys/class/boardinfo/ddr_size" ]; then
        BOARD_MEMORY_SIZE="$(cat /sys/class/boardinfo/ddr_size | tr -d ' \n')"
    else
      echo "No RDK memory size found"
      exit "${EXIT_SUCCESS}"
    fi
}

# Find latest applicable update version
MINIBOOT_UPDATE_IMAGE=""
MINIBOOT_UPDATE_VERSION=0
getMinibootUpdateVersion()
{
   MINIBOOT_UPDATE_VERSION=0
   getMemorySize
   match=".*/disk_nand_minimum_boot_${BOARD_MEMORY_SIZE}GB_3V3_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].img"
   latest="$(find "/lib/firmware/rdk/miniboot/default/" -maxdepth 1 -type f -follow -regex "${match}" | sort -r | head -n1)"
   if [ -f "${latest}" ]; then
      # shellcheck disable=SC2034
      MINIBOOT_UPDATE_VERSION=$(basename "${latest}" | awk -F_ '{print $NF}' | sed 's/\.img//')
      # shellcheck disable=SC2034
      MINIBOOT_UPDATE_IMAGE="${latest}"
   fi
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_sound_devices_select() {
  if [[ "$(get_rdk_type_string)" = *"S100"* || "$(get_rdk_type_string)" = *"s600"* ]];then
    whiptail --msgbox "Please Refer to: \nhttps://developer.d-robotics.cc/rdk_doc/rdk_s/Basic_Application/audio/audio_board_s100 \nfor Audio Board Usage Manual!"  20 "$WT_WIDTH" 1
    return
  fi
  if [ "$INTERACTIVE" = True ]; then
    CUR=$(get_cur_audio_hat)
    board_type_string=$(get_rdk_type_string)
    audio_options=("UNSET")

    if [ "$board_type_string" == "x5_rdk" ]; then
      audio_options=("" "Audio Driver HAT V2" ""  "    4 chn input and 2 chn ouput"  """UNSET""" "    Unset audio driver hat")
    fi


    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "$CUR" --menu "Select Sound Device" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "${audio_options[@]}" 3>&1 1>&2 2>&3)
    RET=$?
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    #get board type (string)
    board_type_string=$(get_rdk_type_string)
    audio_hat_type_string=""
    #if board is unsupport,return
    if [ "$board_type_string" == "null" ]; then
      echo "Unsupport board type"
      return
    fi
    mkdir -p /etc/pulse/
    #if audio is wm8960
    if [ "$FUN" == "WM8960 Audio HAT" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      #remove asound state,for the pa setting
      rm -f /var/lib/alsa/asound.state
      #soft link our pre-set config
      ln -s /etc/hobot_audio_config/wm8960_config/wm8960_asound.state /var/lib/alsa/asound.state
      modprobe snd-soc-wm8960
      modprobe hobot-snd-wm8960
      alsactl restore > /dev/null 2>&1
      #enable wm8960 audo load at boot (ONLY CODEC DRIVER!)
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-wm8960.conf ]; then
        mv  /lib/modprobe.d/blacklist-hobot-codec-wm8960.conf /lib/modprobe.d/blacklist-hobot-codec-wm8960.disable
      fi
      audio_hat_type_string="wm8960"
    fi
    #if audio is es7210+es8156
    if [ "$FUN" == "Audio Driver HAT V1" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      #enable driver auto load at boot (ONLY CODEC DRIVER!)
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-es7210.conf ]; then
        mv /lib/modprobe.d/blacklist-hobot-codec-es7210.conf /lib/modprobe.d/blacklist-hobot-codec-es7210.disable
      fi
      audio_hat_type_string="es7210_es8156"
    fi
    #same as above
    if [ "$FUN" == "Audio Driver HAT V2" ]; then
      if [ "$CUR" != "UNSET" ]; then
        do_unset_audio_hat
        CUR="$FUN"
      fi
      if [ -e /lib/modprobe.d/blacklist-hobot-codec-es7210.conf ]; then
        mv /lib/modprobe.d/blacklist-hobot-codec-es7210.conf /lib/modprobe.d/blacklist-hobot-codec-es7210.disable
      fi
      audio_hat_type_string="es7210_es8156"
    fi
    #if user didn't unset audio hat
    if [ "$FUN" != "UNSET" ]; then
      #splice dtbo name,from option and board
      dtboname=audio_"$audio_hat_type_string"_"$board_type_string"
      #for debug,it will be commented out
      #echo $dtboname
      #set dtoverlay name to config.txt
      if grep -q dtoverlay="$dtboname" /boot/config.txt; then
        echo ""
      else
        echo dtoverlay="$dtboname" >> $CONFIG
      fi
      #stop pulseaudio,sometimes it gives some weird errors
      kill -9 "$(pidof pulseaudio)" > /dev/null 2>&1
      #splice pulse_config
      pulse_config=/etc/hobot_audio_config/"$audio_hat_type_string"_"$board_type_string".pa
      #echo "$pulse_config"
      if [ ! -f "/etc/hobot_audio_config/original_default.pa" ]; then
        #it mean it's first time that we config audio,backup origin default.pa
        cp  /etc/pulse/default.pa /etc/hobot_audio_config/original_default.pa > /dev/null 2>&1
      fi
      #backup config file,and replace it
      if [ -f "$pulse_config" ]; then
        cp  /etc/pulse/default.pa /etc/pulse/default.bak
        cp  "$pulse_config" /etc/pulse/default.pa
        #echo "The original configuration file has been renamed default.bak"
        #echo
      fi
      cp  /etc/hobot_audio_config/99_hobot_audio_module.conf /etc/modules-load.d/
      #enable iis driver audo load at boot
      if [ -e /lib/modprobe.d/blacklist-hobot-iis.conf ]; then
        mv  /lib/modprobe.d/blacklist-hobot-iis.conf /lib/modprobe.d/blacklist-hobot-iis.disable
      fi
    fi
    #set the current audio board type to UNSET step 1
    echo "$FUN" > /etc/hobot_audio_config/cur_audio_hat
    #if user unset audio hat
    if [ "$FUN" == "UNSET" ]; then
      do_unset_audio_hat
      systemctl disable hobot-audio.service
    else
      systemctl enable hobot-audio.service
    fi
    ASK_TO_REBOOT=1
  fi
}
do_unset_audio_hat(){
  #remove auto load module step 1
  directory="/lib/modprobe.d"
  for file in "$directory"/*.disable; do
    if [ -f "$file" ]; then
        new_name="${file%.disable}.conf"
        mv  "$file" "$new_name"
    fi
  done
  #remove auto load module step 2
  rm -f /etc/modules-load.d/01_hobot_audio_module.conf
  #remove alsa config step 3
  rm -f /var/lib/alsa/asound.state
  #restore pulseaudio configuration file step 1
  if [ -f /etc/hobot_audio_config/original_default.pa ]; then
    cp  /etc/hobot_audio_config/original_default.pa /etc/pulse/default.pa > /dev/null 2>&1
  elif [ -f /etc/pulse/default.bak ]; then
    mv  /etc/pulse/default.bak /etc/pulse/default.pa
  fi
  #delete dtoverlay setting step 1
  sed -i '/^dtoverlay=audio_/d' /boot/config.txt
}

# shellcheck disable=SC2120
# When used within srpi-config, input is handled by whiptail
do_imu_devices_select(){

  #imu dtoverlay filename = (dtoverlay)_(imu)_(i2c5)_(x5_rdk).dts/dtbo
  if [[ "$(get_rdk_type_string)" = *"S100"* || "$(get_rdk_type_string)" = *"s600"* ]];then
    whiptail --msgbox "IMU on S100 is being ported... Please wait for official release."  20 "$WT_WIDTH" 1
  fi
  if [ "$INTERACTIVE" = True ]; then
    # CUR=$(get_cur_audio_hat)
    board_type_string=$(get_rdk_type_string)
    dtfilehead="dtoverlay_imu_"
    # audio_options=("UNSET")
    if [ "$board_type_string" == "x5_rdk" ]; then
      # imu_options=(""SPI-Interface" "" "I2C-Interface" """)
      imu_options=("""SPI-Interface"""  "    Use SPI1 as the data interface for IMU."  """I2C-Interface""" "    Use I2C5 as the data interface for IMU." """UNSET""" "    Unset IMU driver hat")
    fi
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --default-item "Onboard" --menu "Set IMU bmi088" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "${imu_options[@]}"  3>&1 1>&2 2>&3)
    RET=$?
    # echo "$FUN""  RET=""$RET"
  else
    FUN=$1
    RET=0
  fi
  if [ $RET -eq 1 ]; then
    # check select if success
    return 0
  elif [ $RET -eq 0 ]; then
    # select not error
    if [ "$FUN" == "UNSET" ]; then
      if grep -q ^dtoverlay="$dtfilehead" $CONFIG; then
        # if exist set data del it
        eval sed -i '/^dtoverlay="$dtfilehead".*/d' $CONFIG
      fi
      return 0
    fi

    if [ "$FUN" == "SPI-Interface" ]; then
      dtfile="$dtfilehead"spi1_"$board_type_string"
    elif [ "$FUN" == "I2C-Interface" ]; then
      dtfile="$dtfilehead"i2c5_"$board_type_string"
    fi
    # check is there right dtoverlay config in config.txt
    if grep -q dtoverlay="$dtfilehead" $CONFIG; then
      # if wrong , sed with right
      eval sed -i 's|dtoverlay="$dtfilehead".*|dtoverlay="$dtfile"|' $CONFIG
    else
      # if not exist, echo it
      echo dtoverlay="$dtfile" >> $CONFIG
    fi

    return 0
  fi
}

do_interface_menu() {
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Interfacing Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "I1 SSH" "Enable/disable remote command line access using SSH" \
      "I2 VNC" "Enable/disable graphical remote desktop access" \
      "I3 Peripheral bus config" "Enable/disable peripheral bus(spi,i2c,serial,i2s,etc.)" \
      "I4 Configure Wi-Fi antenna" "Configure Wi-Fi antennas to use onboard or external antenna" \
      "I5 Audio" "Configure audio peripheral functions" \
      "I6 IMU" "Configure IMU peripheral functions" \
      3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      I1\ *) do_ssh ;;
      I2\ *) do_vnc ;;
      I3\ *) do_peripheral ;;
      I4\ *) do_wifi_antenna ;;
      I5\ *) do_sound_devices_select ;;
      I6\ *) do_imu_devices_select ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_performance_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Performance Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "P1 CPU frequency" "Configure CPU frequency" \
      "P2 ION memory" "Configure ION memory size for BPU and multimedia" \
      3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      P1\ *) do_cpu_frequency_menu ;;
      P2\ *) do_config_ion_memory ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_internationalisation_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Localisation Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
    "L1 Locale" "Configure language and regional settings" \
    "L2 Timezone" "Configure time zone" \
    "L3 Keyboard" "Set keyboard layout to match your keyboard" \
    3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      L1\ *) do_change_locale ;;
      L2\ *) do_change_timezone ;;
      L3\ *) do_configure_keyboard ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_advanced_menu() {
  if is_rdkmd ; then
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Advanced Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "A1 Expand Filesystem" "Ensures that all of the SD card is available" \
      "A2 Network Proxy Settings" "Configure network proxy settings" \
      "A3 Boot Order" "Choose network or USB device boot" \
      3>&1 1>&2 2>&3)
  else
   FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Advanced Options" "$WT_HEIGHT" "$WT_WIDTH"  "$WT_MENU_HEIGHT"  --cancel-button Back --ok-button Select \
      "A1 Expand Filesystem" "Ensures that all of the SD card is available" \
      "A2 Network Proxy Settings" "Configure network proxy settings" \
      3>&1 1>&2 2>&3)
  fi
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      A1\ *) do_expand_rootfs ;;
      A2\ *) do_proxy_menu ;;
      A3\ *) do_boot_order ;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_proxy_menu() {
  FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --menu "Network Proxy Settings" "$WT_HEIGHT" "$WT_WIDTH" "$WT_MENU_HEIGHT" --cancel-button Back --ok-button Select \
    "P1 All" "Set the same proxy for all schemes" \
    "P2 HTTP" "Set the HTTP proxy" \
    "P3 HTTPS" "Set the HTTPS/SSL proxy" \
    "P4 FTP" "Set the FTP proxy" \
    "P5 RSYNC" "Set the RSYNC proxy" \
    "P6 Exceptions" "Set addresses for which a proxy server should not be used" \
    3>&1 1>&2 2>&3)
  RET=$?
  if [ $RET -eq 1 ]; then
    return 0
  elif [ $RET -eq 0 ]; then
    case "$FUN" in
      P1\ *) do_proxy all ;;
      P2\ *) do_proxy http ;;
      P3\ *) do_proxy https ;;
      P4\ *) do_proxy ftp ;;
      P5\ *) do_proxy rsync ;;
      P6\ *) do_proxy no;;
      *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
    esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
  fi
}

do_finish() {
  if [ $ASK_TO_REBOOT -eq 1 ]; then
    if whiptail --yesno "Would you like to reboot now?" 20 60 2; then # yes
      sync
      reboot
    fi
  fi
  exit 0
}

#
# Interactive use loop
#
if [ "$INTERACTIVE" = True ]; then
  [ -e $CONFIG ] || touch $CONFIG
  calc_wt_size
  while [ "$USER" = "root" ] || [ -z "$USER" ]; do
    if ! USER=$(whiptail --inputbox "srpi-config could not determine the default user.\\n\\nWhat user should these settings apply to?" 20 60 pi 3>&1 1>&2 2>&3); then
      return 0
    fi
  done
  backtitle=$(cat /proc/device-tree/model | tr -d '\0')
  while true; do
    FUN=$(whiptail --title "RDK Software Configuration Tool (srpi-config)" --backtitle "${backtitle}" --menu "Setup Options" "$WT_HEIGHT" "$WT_WIDTH" "$WT_MENU_HEIGHT" --cancel-button Finish --ok-button Select \
      "1 System Options" "Configure system settings" \
      "2 Display Options" "Configure display settings" \
      "3 Interface Options" "Configure connections to peripherals" \
      "4 Performance Options" "Configure performance settings" \
      "5 Localisation Options" "Configure language and regional settings" \
      "6 Advanced Options" "Configure advanced settings" \
      "8 Update" "Update this tool to the latest version" \
      "9 About srpi-config" "Information about this configuration tool" \
      3>&1 1>&2 2>&3)
    RET=$?
    if [ $RET -eq 1 ]; then
      do_finish
    elif [ $RET -eq 0 ]; then
      case "$FUN" in
        1\ *) do_system_menu ;;
        2\ *) do_display_menu ;;
        3\ *) do_interface_menu ;;
        4\ *) do_performance_menu ;;
        5\ *) do_internationalisation_menu ;;
        6\ *) do_advanced_menu ;;
        8\ *) do_update ;;
        9\ *) do_about ;;
        *) whiptail --msgbox "Programmer error: unrecognized option" 20 60 1 ;;
      esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1
    else
      exit 1
    fi
  done
fi
