#!/bin/bash
################################################################################
# Copyright 2025 ModalAI Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# 4. The Software is used solely in conjunction with devices provided by
#    ModalAI Inc.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
################################################################################

NAME="voxl-modem"
SERVICE_FILE="${NAME}.service"
CONFIG_FILE="/etc/modalai/${NAME}.conf"
MAVLINK_CONFIG_FILE="/etc/modalai/voxl-mavlink-server.conf"
USER=$(whoami)

INTERFACE_FILE=/etc/network/interfaces
PLATFORM=$(uname -n)
MODEM=""
APN=""
PORT=""
MODALLINK="FALSE"

print_usage () {
	echo ""
	echo "Config script for voxl-modem"
	echo ""
	echo ""
	echo "voxl-configure-modem enable"
	echo "voxl-configure-modem disable"
	echo "voxl-configure-modem factory_enable"
	echo "voxl-configure-modem doodle"
	echo "voxl-configure-modem doodle-vrx"
	echo "voxl-configure-modem dtc"
	echo "voxl-configure-modem dtc-vrx"
	echo "voxl-configure-modem microhard"
	echo "voxl-configure-modem v2-tmobile"
	echo ""
	echo "show this help message:"
	echo "voxl-configure-modem help"
	echo ""
}

## sanity checks
if [ "${USER}" != "root" ]; then
	echo "Run this script as the root user"
	exit 1
fi

reset_config_file_to_default(){
	echo "wiping old config file"
	cp /share/modalai/voxl-modem.conf ${CONFIG_FILE}
}

## copy over default config file if missing
if [ ! -f ${CONFIG_FILE} ]; then
	echo "Making new config file ${CONFIG_FILE}"
	cp /share/modalai/voxl-modem.conf ${CONFIG_FILE}
fi

## convert argument to lower case for robustness
arg=$(echo "$1" | tr '[:upper:]' '[:lower:]')

parse_json(){
    echo $CONF_FILE | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'$1'"]'
}

## set most parameters which don't have quotes in json
set_param () {
	if [ "$#" != "2" ]; then
		echo "set_param expected 2 args"
		exit 1
	fi

	# remove quotes if they exist
	var=$1
	var="${var%\"}"
	var="${var#\"}"
	val=$2
	val="${val%\"}"
	val="${val#\"}"

	sed -E -i "/\"$var\":/c\	\"$var\":	$val," ${CONFIG_FILE}
}

## set voxl-mavlink-server param, no quotes
set_mavlink_param () {
	if [ "$#" != "2" ]; then
		echo "set_param expected 2 args"
		exit 1
	fi

	# remove quotes if they exist
	var=$1
	var="${var%\"}"
	var="${var#\"}"
	val=$2
	val="${val%\"}"
	val="${val#\"}"

	if [ -f "$MAVLINK_CONFIG_FILE" ]; then
		sed -E -i "/\"$var\":/c\	\"$var\":	$val," ${MAVLINK_CONFIG_FILE}
	else
		echo "[WARNING] Failed to set $MAVLINK_CONFIG_FILE param, file does not exist"
	fi

}

## set string parameters which need quotes in json
set_param_string () {
	if [ "$#" != "2" ]; then
		echo "set_param_string expected 2 args"
		exit 1
	fi

	var=$1
	var="${var%\"}"
	var="${var#\"}"

	sed -E -i "/\"$var\":/c\	\"$var\":	\"$2\"," ${CONFIG_FILE}
}

disable_service_and_exit () {
	echo "disabling ${NAME} systemd service"
	systemctl disable ${SERVICE_FILE}
	echo "stopping ${NAME} systemd service"
	systemctl stop ${SERVICE_FILE}
	echo "Done configuring ${NAME}"
	exit 0
}

enable_service_and_exit () {
	echo "reloading systemd services"
	systemctl daemon-reload
	echo "enabling ${NAME} systemd service"
	systemctl enable ${SERVICE_FILE}
	echo "starting ${NAME} systemd service"
	systemctl restart ${SERVICE_FILE}
	echo "DONE configuring ${NAME}"
	if [ "$MODALLINK" == "TRUE" ]
	then
		systemctl enable modallink-relink.service
		echo "starting modallink-relink systemd service"
		systemctl restart modallink-relink.service
	fi
	exit 0
}

lte_questions () {
	## ask ModalLink question
	echo " "
	echo "Are you attempting to connect to ModalLink? (not common)"
	select opt in "yes" "no"; do
	case $opt in
	yes )
		set_param_string modallink true
		APN="modalai"
		MODALLINK="TRUE"
		set_param_string apn modalai
		break;;
	no )
		set_param_string modallink false

		## ask APN question
		echo " "
		echo "Which APN is correct for your SIM card?"
		echo -e "\nAT&T - IoT device - APN: m2m.com.attz"
		echo "AT&T - Laptop or Tablet - APN: broadband"
		echo "AT&T - Smartphone - APN: phone"
		echo "T-Mobile - APN: fast.t-mobile.com"
		echo "Verizon - APN: vzwinternet"
		echo "Google Fi - APN: h2g2"

		echo
		select opt in "m2m.com.attz" "broadband" "phone" "fast.t-mobile.com" "vzwinternet" "googlefi" "Custom"; do
		case $opt in
		m2m.com.attz )
			set_param_string apn m2m.com.attz
			APN="m2m.com.attz"
			break;;
		broadband )
			set_param_string apn broadband
			APN="broadband"
			break;;
		phone )
			set_param_string apn phone
			APN="phone"
			break;;
		fast.t-mobile.com )
			set_param_string apn fast.t-mobile.com
			APN="fast.t-mobile.com"
			break;;
		vzwinternet )
			set_param_string apn vzwinternet
			APN="vzwinternet"
			break;;
		googlefi )
			set_param_string apn h2g2
			APN="h2g2"
			break;;
		Custom )
    		echo "Please enter a custom APN"
    		read CUSTOM_APN
			set_param_string apn $CUSTOM_APN
			APN=$CUSTOM_APN
			break;;
		*)
			echo "invalid option"
			esac
		done

		## ask world modem question
		echo " "
		echo "Select modem region:"
		select opt in "Americas" "Europe/Middle-East/Asia"; do
		case $opt in
		Americas )
			set_param_string world false
			break;;
		Europe/Middle-East/Asia )
			set_param_string world true
			break;;
		*)
			echo "invalid option"
			esac
		done
			break;;
	*)
		echo "invalid option"
		esac
	done
	
}

microhard_questions () {
	MICROHARD_IP="192.168.168.100"

	## ask IP question
	echo " "
	echo "Enter the IP address you would like to the VOXL to use on the Microhard network:"
	echo "Note: The chosen IP address must be of the form: 192.168.168.XXX"
	echo -e "\nDefault - 192.168.168.100"
	
	echo
	select opt in "default" "custom"; do
	case $opt in
	default )
		set_param_string microhard_ip 192.168.168.100
		break;;
	custom )
    	echo "Please enter a custom IP address"
    	read CUSTOM_IP
		set_param_string microhard_ip $CUSTOM_IP
		MICROHARD_IP=$CUSTOM_IP
		break;;
	*)
		echo "invalid option"
		esac
	done

	# Make network directory if it doesn't exist
	mkdir -p /etc/network

	## copy over network interface file
	echo "Making new interface file ${INTERFACE_FILE}"
	cp /share/modalai/interfaces ${INTERFACE_FILE}

	# Modify interface file for static ip
	sed -i 's/192.168.168.100/'${MICROHARD_IP}'/1' ${INTERFACE_FILE}
}

dtc_questions() {
	DTC_IP="192.168.0.100"

	## ask IP question
	echo " "
	echo "Enter the IP address you would like to the VOXL to use on the DTC network:"
	echo "Note: The chosen IP address must be of the form: 192.168.0.XXX"
	echo -e "\nDefault - 192.168.0.100"

		
	echo
	select opt in "default" "custom"; do
	case $opt in
	default )
		set_param_string dtc_ip 192.168.0.100
		break;;
	custom )
    	echo "Please enter a custom IP address"
    	read CUSTOM_IP
		set_param_string dtc_ip $CUSTOM_IP
		DTC_IP=$CUSTOM_IP
		break;;
	*)
		echo "invalid option"
		esac
	done

	# Make network directory if it doesn't exist
	mkdir -p /etc/network

	## copy over network interface file
	echo "Making new interface file ${INTERFACE_FILE}"
	cp /share/modalai/interfaces ${INTERFACE_FILE}
}

doodle_questions () {
	## ask IP questions
	echo " "
	echo "Enter the IP address you would like to the VOXL to use on the Doodle network:"
	echo "Note: The chosen IP address must be of the form: 10.223.0.XXX"
	echo -e "\nDefault - 10.223.0.100"
	
	echo
	select opt in "default" "custom"; do
	case $opt in
	default )
		set_param_string doodle_ip 10.223.0.100
		break;;
	custom )
    	echo "Please enter a custom IP address"
    	read CUSTOM_IP
		set_param_string doodle_ip $CUSTOM_IP
		break;;
	*)
		echo "invalid option"
		esac
	done

	echo " "
	echo "Enter the network interface you would like to the VOXL to use on the Doodle network:"
	echo -e "\nDefault - eth1"

	echo
	select opt in "default" "custom"; do
	case $opt in
	default )
		set_param_string doodle_interface eth1
		set_param_string doodle_ip 10.223.0.100
		break;;
	custom )
    	echo "Please enter a custom network interface"
    	read CUSTOM_INTERFACE
		set_param_string doodle_interface $CUSTOM_INTERFACE
		break;;
	*)
		echo "invalid option"
		esac
	done
	
	echo "Setting udp_mtu in $MAVLINK_CONF_FILE"
	set_mavlink_param udp_mtu 500
}

modem_question_apq8096 () {
	## ask modem type question
	echo " "
	echo "What type of modem are you using?"
	echo
	select opt in "v1" "v2" "quectel" "microhard" "dtc" "doodle"; do
	case $opt in
	v1 )
		set_param_string modem_type v1
		MODEM="v1"
		lte_questions
		break;;
	v2)
		set_param_string modem_type v2
		MODEM="v2"
		lte_questions
		break;;
	quectel)
		set_param_string modem_type quectel
		MODEM="quectel"
		lte_questions
		break;;
	microhard)
		set_param_string modem_type microhard
		MODEM="microhard"
		microhard_questions
		break;;
	dtc)
		set_param_string modem_type dtc
		MODEM="dtc"
		dtc_questions
		break;;
	doodle)
		set_param_string modem_type doodle
		MODEM="doodle"
		doodle_questions
		break;;
	*)
		echo "invalid option"
		esac
	done
}

modem_question_qrb5165 () {
	## ask modem type question
	echo " "
	echo "What type of modem are you using?"
	echo
	select opt in "v2" "microhard" "dtc" "doodle" "quectel" "em9X91" ; do
	case $opt in
	v2)
		set_param_string modem_type v2
		MODEM="v2"
		lte_questions
		break;;
	microhard)
		set_param_string modem_type microhard
		MODEM="microhard"
		microhard_questions
		break;;
	dtc)
		set_param_string modem_type dtc
		MODEM="dtc"
		dtc_questions
		systemctl enable voxl-modem
		break;;
	doodle)
		set_param_string modem_type doodle
		MODEM="doodle"
		doodle_questions
		systemctl enable voxl-modem-doodle
		break;;
	doodle-vrx)
		set_param_string modem_type doodle
		MODEM="doodle"
		doodle_questions
		systemctl enable voxl-modem-doodle
		break;;
	dtc-vrx)
		set_param_string modem_type dtc
		MODEM="dtc"
		dtc_questions
		systemctl enable voxl-modem
		break;;
	quectel)
		set_param_string modem_type quectel
		MODEM="quectel"
		lte_questions
		break;;
	em9X91)
		set_param_string modem_type em9191
		MODEM="em9191"
		lte_questions
		break;;
	*)
		echo "invalid option"
		esac
	done
}

## parse arguments
case ${arg} in
	"")
		echo "Starting interactive mode"
		;;
	"h"|"-h"|"help"|"--help")
		print_usage
		exit 0
		;;
	"disable")
		disable_service_and_exit
		;;
	"enable")
		enable_service_and_exit
		;;
	"factory_enable")
		reset_config_file_to_default
		enable_service_and_exit
		;;
	"doodle")
		reset_config_file_to_default
		set_param_string modem_type doodle
		set_param_string doodle_ip 10.223.0.100
		set_mavlink_param udp_mtu 500
		enable_service_and_exit
		;;
	"doodle-vrx")
		reset_config_file_to_default
		set_param_string modem_type doodle
		set_param_string doodle_ip 10.223.0.101
		set_param_string doodle_interface eth1
		set_mavlink_param udp_mtu 500
		enable_service_and_exit
		;;
	"dtc")
		reset_config_file_to_default
		set_param_string modem_type dtc
		set_param_string dtc_ip 192.168.0.100
		enable_service_and_exit
		;;
	"dtc-vrx")
		reset_config_file_to_default
		set_param_string modem_type dtc
		set_param_string doodle_ip 192.168.0.101
		set_param_string doodle_interface eth1
		enable_service_and_exit
		;;
	"microhard")
		reset_config_file_to_default
		set_param_string modem_type microhard
		set_param_string microhard_ip 192.168.168.100
		enable_service_and_exit
		;;
	"v2-tmobile")
		reset_config_file_to_default
		set_param_string modem_type v2
		set_param_string apn fast.t-mobile.com
		set_param_string world false
		set_param_string modallink false
		enable_service_and_exit
		;;
	*)
		echo "invalid option: $arg"
		exit 1
esac


# Ask modem question for specified platform
if [ $PLATFORM == "apq8096" ]
then
	modem_question_apq8096
else
	modem_question_qrb5165
fi

# set port
if [ "$MODEM" == "v1" ]
then
	PORT="ttyACM0"
elif [ "$MODEM" == "v2" ]
then
	PORT="ttyUSB2"
fi 

# set apn
if [ "$MODEM" == "v1" ] || [ "$MODEM" == "v2" ]
then
	# Loop until correct /dev/tty device is available
	if [ "$MODEM" == "v2" ]
	then
		if [ $PLATFORM == "apq8096" ]
		then
			enable-sierra.sh &> /dev/null
		fi
	elif [ "$MODEM" == "v1" ]
	then
		voxl-modem --feather_configure
	fi
    rc=1
    echo -e "\nWaiting for "${PORT}"..."
    while [ $rc -ne 0 ]; do
        ls /dev | grep "$PORT"
        rc=$?
        sleep 1
    done

    echo -e ${PORT}" initialized"

    # set APN
    echo -e "\nSetting APN: "${APN}
    echo "AT+CGDCONT=1,\"IP\",\"${APN}\",\"0.0.0.0\",0,0,0,0" > /dev/${PORT}
fi
# all done!

if [ $PLATFORM == "qrb5165-rb5" ] || [ $PLATFORM == "m0104" ] || [ $PLATFORM == "m0054" ] || [ $PLATFORM == "m0052" ]
then
    echo -e "\nqrb5165 based device detected"

	if [ "$MODEM" == "v2" ]
	then
		echo -e "Writing to APN file..."
		touch /etc/qmi-network.conf
		echo "APN=$APN" > /etc/qmi-network.conf

		echo -e "Enabling DNS..."
		enable-dns.sh
	fi
    

fi

enable_service_and_exit
