#!/bin/bash
#
# Author   : Gaston Gonzalez
# Date     : 6 November 2024
# Updated  : 5 February 2025
# Purpose  : Configures the system for a specific mode of operation

# Use a simple text file to save the state of the last mode selected
MODE_STATUS_FILE="${HOME}/.config/emcomm-tools/et-mode"

# List of supported modes of operation
MODE_ID_NONE="none"
MODE_ID_APRS_DIGIPEATER="aprs-digipeater" 
MODE_ID_APRS_CLIENT="aprs-client" 
MODE_ID_BBS_CLIENT="bbs-client" 
MODE_ID_BBS_CLIENT2="bbs-client2" 
MODE_ID_CHAT_CLIENT="chat-chattervox" 
MODE_ID_PACKET_DIGIPEATER="packet-digipeater" 
MODE_ID_WINLINK_ARDOP="winlink-ardop" 
MODE_ID_WINLINK_PACKET="winlink-packet" 
MODE_ID_WINLINK_VARA_HF="winlink-vara-hf" 
MODE_ID_WINLINK_VARA_FM="winlink-vara-fm" 

# Default to 1200 baud
PACKET_MODE=simple

# Attempt to stop all EmComm Tools services regardless if they are running.
stop_all_services() {
  et-kill-all 
}

exit_on_service_failure() {
  local systemd_unit_name="$1"
  systemctl is-active --user --quiet "${systemd_unit_name}"
  if [ $? -ne 0 ]; then
    et-log "Can't start mode. ${systemd_unit_name} failed to start."
    exit 1
  fi
}

TIMEOUT=15  # Total time to wait in seconds
INTERVAL=2  # Interval between checks in seconds

start_and_wait_for_service() {
  local systemd_unit_name="$1"
  local elapsed=0

  et-log "Starting ${systemd_unit_name}..."
  systemctl --user start ${systemd_unit_name}

  et-log "Waiting for ${systemd_unit_name} to become active..."

  while ! systemctl is-active --user --quiet "${systemd_unit_name}"; do
      sleep "$INTERVAL"
      elapsed=$((elapsed + INTERVAL))
      if [ "$elapsed" -ge "$TIMEOUT" ]; then
          et-log "Timeout reached. ${systemd_unit_name} failed to start."
          exit 1
      fi
      et-log "Waiting for ${systemd_unit_name} to become active..."
  done

  # Some applications even when started still need a bit of extra time to be available. 
  # Add a short think time of 2 seconds. The ARDOP modem requies extra time.
  sleep 2

  # Do one more check to ensure that we are running, otherwise exit.
  exit_on_service_failure ${systemd_unit_name}
}

start_and_wait_for_vara() {
  local vara_cmd="$1"
  local elapsed=0

  et-log "Starting ${vara_cmd}..."
  ${vara_cmd} &

  et-log "Waiting for ${vara_cmd} to become active..."
  
  while true; do
    CHECK_VARA=$(ps -ef | grep "[V]ARA")
    if [ $? -eq 0 ]; then
      break
    fi  

    sleep "$INTERVAL"
    elapsed=$((elapsed + INTERVAL))
    if [ "$elapsed" -ge "$TIMEOUT" ]; then
        et-log "Timeout reached. ${systemd_unit_name} failed to start."
        exit 1
    fi
    et-log "Waiting for ${vara_cmd} to become active..."
  done
}

select_direwolf_mode () {
  packet_mode=()
  packet_mode+=("simple" "1200 baud (default for VHF/UHF)")
  packet_mode+=("9600" "9600 baud (VHF/UHF)")
  packet_mode+=("300" "300 baud (HF)")

  PACKET_MODE=$(dialog --clear --menu "Select a modem" 10 60 10 "${packet_mode[@]}" 3>&1 1>&2 2>&3)
  exit_status=$?

  if [ "${PACKET_MODE}" == "9600" ]; then
    dialog --title "Note on 9600 Baud" --msgbox "9600 baud is only supported on limited radios and typically requires a special cable.\n\nDon't forget to set the packet settings to 9600 on the radio." 0 0
  fi 

  tput sgr 0 && clear

  if [ ${exit_status} -ne 0 ]; then
    et-log "No modem selected. Mode will not be started."
    exit 1
  fi  
}

select_winlink_mode () {
  winlink_mode=()

  BLUETOOTH_TNC_CHECK=$(ps -ef | grep "[r]fcomm connect")
  if [[ $? -eq 0 ]]; then
    et-log "AX.25 over Bluetooth connected. Configuring Winlink for native AX.25"
    start_and_wait_for_service et-service-winlink-native-packet
    min http://localhost:8080
    exit 0
  fi
}

# Build list of options
options=()
options+=("${MODE_ID_NONE}" "No mode selected")
options+=("${MODE_ID_APRS_CLIENT}" "APRS Client (YAAC)")
options+=("${MODE_ID_BBS_CLIENT}" "BBS Client (Paracon)")
options+=("${MODE_ID_BBS_CLIENT2}" "BBS Client (QtTermTCP)")
options+=("${MODE_ID_CHAT_CLIENT}" "Chat (chattervox)")
options+=("${MODE_ID_APRS_DIGIPEATER}" "APRS Digipeater")
options+=("${MODE_ID_PACKET_DIGIPEATER}" "Packet Digipeater")
options+=("${MODE_ID_WINLINK_PACKET}" "Winlink over VHF/UHF (AX.25 Packet)")

if [ -e "${HOME}/.wine32/drive_c/VARA FM/VARAFM.exe" ]; then
  options+=("${MODE_ID_WINLINK_VARA_FM}" "Winlink over VHF/UHF (VARA FM)")
fi

options+=("${MODE_ID_WINLINK_ARDOP}" "Winlink over HF (ARDOP)")

if [ -e "${HOME}/.wine32/drive_c/VARA/VARA.exe" ]; then
  options+=("${MODE_ID_WINLINK_VARA_HF}" "Winlink over HF (VARA HF)")
fi

# Prompt user for option and save exit status
SELECTED_MODE=$(dialog --clear --menu "Select a mode:" 18 65 10 "${options[@]}" 3>&1 1>&2 2>&3)
exit_status=$?

tput sgr 0 && clear

if [ $exit_status -eq 0 ]; then

  stop_all_services

  echo ${SELECTED_MODE} > ${MODE_STATUS_FILE}

  case ${SELECTED_MODE} in
    ${MODE_ID_NONE})
      et-log "No mode selected"
    ;;
    ${MODE_ID_APRS_DIGIPEATER})
      systemctl --user start et-service-direwolf-aprs-digipeater
      et-log "APRS digipeater now running."
    ;;
    ${MODE_ID_APRS_CLIENT})
      start_and_wait_for_service et-service-direwolf-simple
      et-yaac start
    ;;
    ${MODE_ID_BBS_CLIENT})
      select_direwolf_mode
      et-log "Using ${PACKET_MODE} as the modem speed."

      start_and_wait_for_service et-service-direwolf-${PACKET_MODE}
      et-log "Starting Paracon."
      et-paracon start
    ;;
    ${MODE_ID_BBS_CLIENT2})
      select_direwolf_mode
      et-log "Using ${PACKET_MODE} as the modem speed."

      start_and_wait_for_service et-service-direwolf-${PACKET_MODE}

      et-log "Starting QtTermTCP."
      et-qttermtcp start
    ;;
    ${MODE_ID_CHAT_CLIENT})
      start_and_wait_for_service et-service-direwolf-simple
      et-log "Starting chattervox"
      et-chattervox start
    ;;
    ${MODE_ID_PACKET_DIGIPEATER})
      systemctl --user start et-service-direwolf-packet-digipeater
      et-log "Packet digipeater now running."
    ;;
    ${MODE_ID_WINLINK_ARDOP}) 
      et-log "Using ${PACKET_MODE} as the modem speed."
      start_and_wait_for_service et-service-ardop
      start_and_wait_for_service et-service-winlink-ardop
      min http://localhost:8080
    ;;
    ${MODE_ID_WINLINK_PACKET})
      select_winlink_mode
      start_and_wait_for_service et-service-direwolf-simple 
      start_and_wait_for_service et-service-winlink-packet
      min http://localhost:8080
    ;;
    ${MODE_ID_WINLINK_VARA_FM})
      dialog --title "User Action Required" --msgbox "VARA FM is not a plug and play mode. You must configure VARA manually." 10 50
      tput sgr 0 && clear
      start_and_wait_for_vara et-vara-fm
      et-winlink start-vara-fm &
      sleep 1
      min http://localhost:8080 2>/dev/null
    ;;
    ${MODE_ID_WINLINK_VARA_HF})
      dialog --title "User Action Required" --msgbox "VARA HF is not a plug and play mode. You must configure VARA manually." 10 50
      tput sgr 0 && clear
      start_and_wait_for_vara et-vara-hf
      et-winlink start-vara-hf &
      sleep 1
      min http://localhost:8080
    ;;
    *)
      et-log "Mode ${SELECTED_MODE} not yet supported"
      exit 1
    ;;
  esac

else
  et-log "No mode selected"
  echo ${MODE_ID_NONE} > ${MODE_STATUS_FILE}
  exit 1
fi
