#!/bin/bash

# Look at voxl-modem.conf to determine MODEM and APN
CONF_FILE=$(cat /etc/modalai/voxl-modem.conf)
PLATFORM=$(uname -n)

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


MODEM=$(parse_json modem_type)
APN=$(parse_json apn)
WORLD=$(parse_json world)
DOODLE_IP=$(parse_json doodle_ip)
DTC_IP=$(parse_json dtc_ip)

# Try to find the interface that uses the smsc95xx driver
DOODLE_INTERFACE=$(for iface in $(ls /sys/class/net); do
    driver=$(ethtool -i "$iface" 2>/dev/null | awk '/driver:/ {print $2}')
    if [ "$driver" = "smsc95xx" ]; then
        echo "$iface"
        break
    fi
done)

# Fallback if not found
if [ -z "$DOODLE_INTERFACE" ]; then
    DOODLE_INTERFACE=$(parse_json doodle_interface)
fi

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

        INTERFACE="wwan0"
        device="Sierra"

        # Check if the interface is up
        while ! ip link show $INTERFACE up >/dev/null 2>&1; do
            echo "Waiting for $INTERFACE to come up..."
            sleep 1
        done

        echo "$INTERFACE is up!"

        # Check if the device is detected in lsusb
        while ! lsusb | grep -q "$device"; do
            echo "Waiting for $device to be detected..."
            sleep 1
        done

        echo "$device detected!"
        sleep 1

        # Stop any existing connection first before changing data format
        QMI_STATE_FILE="/tmp/qmi-network-state-cdc-wdm0"
        if [ -f "$QMI_STATE_FILE" ]; then
            echo -e "\nClearing stale qmi network state..."
            sudo qmi-network /dev/cdc-wdm0 stop
            sudo rm -f "$QMI_STATE_FILE"
        fi

        echo -e "\nSetting raw ip mode..."
        sudo ifconfig wwan0 down
        echo 'Y' | sudo tee /sys/class/net/wwan0/qmi/raw_ip > /dev/null
        sudo qmicli -d /dev/cdc-wdm0 --set-expected-data-format=raw-ip
        # Verify and re-apply raw_ip if needed (kernel sometimes reverts it)
        sleep 1
        RAW_IP_VAL=$(cat /sys/class/net/wwan0/qmi/raw_ip 2>/dev/null)
        if [ "$RAW_IP_VAL" != "Y" ]; then
            echo "Raw IP reverted to $RAW_IP_VAL, forcing it again..."
            echo 'Y' | sudo tee /sys/class/net/wwan0/qmi/raw_ip > /dev/null
        fi
        sudo ifconfig wwan0 up

        echo -e "\nStarting qmi network..."
        while true; do
            sudo qmi-network /dev/cdc-wdm0 start
            return_code=$?

            if [ $return_code -eq 0 ]; then
                echo "Command executed successfully."
                break
            else
                echo "Error detected! Retrying..."
                sudo qmi-network /dev/cdc-wdm0 stop
                sudo rm -f "$QMI_STATE_FILE"
                sleep 1
            fi
        done

        echo -e "\Checking qmi network status..."
        sudo qmi-network /dev/cdc-wdm0 status

        echo -e "\nConfiguring IP address from QMI settings..."
        # Get IP configuration from the modem
        QMI_SETTINGS=$(sudo qmicli -d /dev/cdc-wdm0 --wds-get-current-settings 2>/dev/null)

        # Parse IP address and gateway
        IP_ADDR=$(echo "$QMI_SETTINGS" | grep "IPv4 address:" | awk '{print $3}')
        NETMASK=$(echo "$QMI_SETTINGS" | grep "IPv4 subnet mask:" | awk '{print $4}')
        GATEWAY=$(echo "$QMI_SETTINGS" | grep "IPv4 gateway address:" | awk '{print $4}')
        DNS1=$(echo "$QMI_SETTINGS" | grep "IPv4 primary DNS:" | awk '{print $4}')
        DNS2=$(echo "$QMI_SETTINGS" | grep "IPv4 secondary DNS:" | awk '{print $4}')

        # Convert netmask to CIDR notation
        CIDR=$(ipcalc -p "$IP_ADDR" "$NETMASK" 2>/dev/null | cut -d= -f2)
        if [ -z "$CIDR" ]; then
            # Fallback if ipcalc not available - common netmasks
            case "$NETMASK" in
                255.255.255.255) CIDR=32 ;;
                255.255.255.252) CIDR=30 ;;
                255.255.255.248) CIDR=29 ;;
                255.255.255.240) CIDR=28 ;;
                255.255.255.0) CIDR=24 ;;
                255.255.0.0) CIDR=16 ;;
                255.0.0.0) CIDR=8 ;;
                *) CIDR=29 ;; # Default fallback
            esac
        fi

        echo "IP: $IP_ADDR/$CIDR Gateway: $GATEWAY DNS: $DNS1, $DNS2"

        # Try udhcpc first for carriers that support DHCP
        echo -e "\nTrying DHCP first..."
        sudo pkill -f "udhcpc.*wwan0" 2>/dev/null
        timeout 5 sudo udhcpc -i wwan0 -n -q 2>/dev/null

        # Check if DHCP worked, if not apply static IP from QMI
        if ! ip addr show wwan0 | grep -q "inet "; then
            echo "DHCP failed, applying static IP from QMI..."
            sudo ip addr flush dev wwan0
            sudo ip addr add "$IP_ADDR/$CIDR" dev wwan0
        fi

        echo "Configuring DNS for wwan0..."
        if command -v resolvectl >/dev/null 2>&1; then
            if [ -n "$DNS1" ] && [ -n "$DNS2" ]; then
                sudo resolvectl dns wwan0 "$DNS1" "$DNS2"
            else
                sudo resolvectl dns wwan0 8.8.8.8 1.1.1.1
            fi
            sudo resolvectl domain wwan0 "~."
        elif command -v systemd-resolve >/dev/null 2>&1; then
            if [ -n "$DNS1" ] && [ -n "$DNS2" ]; then
                sudo systemd-resolve --set-dns="$DNS1" --set-dns="$DNS2" --interface=wwan0
            else
                sudo systemd-resolve --set-dns=8.8.8.8 --set-dns=1.1.1.1 --interface=wwan0
            fi
            sudo systemd-resolve --set-domain="~." --interface=wwan0
        fi

        echo -e "\nFinished connect to network."
        # Remove all default routes
        while sudo ip route del default 2>/dev/null; do :; done
        # Add the new default route
        if [ -n "$GATEWAY" ]; then
            sudo ip route add default via "$GATEWAY" dev "$INTERFACE" metric 50
            echo "Default route set to $INTERFACE via $GATEWAY"
        else
            sudo ip route add default dev "$INTERFACE" scope link metric 50
            echo "Default route set to $INTERFACE"
        fi

        # Monitor and maintain the route - keep the service running
        echo "Monitoring network connection..."
        while true; do
            # Check if default route via wwan0 exists
            if ! ip route | grep -q "default.*$INTERFACE"; then
                echo "Default route lost, re-adding..."
                while sudo ip route del default dev usb0 2>/dev/null; do :; done
                while sudo ip route del default dev eth0 2>/dev/null; do :; done
                if [ -n "$GATEWAY" ]; then
                    sudo ip route add default via "$GATEWAY" dev "$INTERFACE" metric 50
                else
                    sudo ip route add default dev "$INTERFACE" scope link metric 50
                fi
            fi
            sleep 5
        done
    elif [ $MODEM == "quectel" ]
    then
        # Setting mode preference
        echo -e "\Setting mode preference to LTE / 5G"
        echo -ne "AT+QNWPREFCFG=\"mode_pref\",LTE:NR5G\r" | busybox microcom -t 1000 /dev/ttyUSB2

        # Loop forever trying to get the cellular link up.
        echo -e "\nInitalizing cellular connection..."
        loop=1
        while [ $loop -ne 0 ]; do
            quectel-CM -s $APN
        done
    elif [ $MODEM == "doodle" ]
    then
        echo -e "\nWaiting for $DOODLE_INTERFACE..."
        rc=1
        while [ $rc -ne 0 ]; do
            ifconfig -s | grep $DOODLE_INTERFACE
            rc=$?
            sleep 1
        done

        echo -e "\n$DOODLE_INTERFACE initialized"

        # loop and re-set IP if network interface goes down and back up
        while true
        do
            # grab ip address from $DOODLE_INTERFACE
            doodle_ip_curr=$(ip -4 addr show $DOODLE_INTERFACE | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)

            # if it's not what we expect, fix it
            if [[ "$doodle_ip_curr" != *"$DOODLE_IP"* ]]; then
                echo "setting IP address to: $DOODLE_IP"
                ifconfig $DOODLE_INTERFACE $DOODLE_IP netmask 255.0.0.0 up
            fi
            sleep 1
        done
    
    elif [ $MODEM == "microhard" ]
    then
        echo -e "\nInitializing Microhard modem..."
        voxl-modem --microhard_configure

    elif [ $MODEM == "dtc" ]
    then
        echo -e "\nInitializing DTC modem..."
        echo -e "\nWaiting for eth0..."
        rc=1
        while [ $rc -ne 0 ]; do
            ifconfig -s | grep eth0
            rc=$?
            sleep 1
        done

        echo -e "\neth0 initialized"

        # loop and re-set IP if network interface goes down and back up
        while true
        do
            # grab ip address from eth0
            eth0_ip_curr=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)

            # if it's not what we expect, fix it
            if [[ "$eth0_ip_curr" != *"$DTC_IP"* ]]; then
                echo "setting IP address to: $DTC_IP"
                ifconfig eth0 $DTC_IP netmask 255.0.0.0 up
            fi
            sleep 1
        done
        
    elif [ $MODEM == "em9191" ]
    then

        INTERFACE="wwan0"
        device="Sierra"

        # Check if the interface is up
        while ! ip link show $INTERFACE up >/dev/null 2>&1; do
            echo "Waiting for $INTERFACE to come up..."
            sleep 1
        done

        echo "$INTERFACE is up!"

        # Check if the device is detected in lsusb
        while ! lsusb | grep -q "$device"; do
            echo "Waiting for $device to be detected..."
            sleep 1
        done

        echo "$device detected!"
        sleep 1

        echo -e "\nStarting qmi network..."
        while true; do
            qmicli --device=/dev/cdc-wdm0 --device-open-proxy --wds-start-network="ip-type=4,apn=$APN" --client-no-release-cid
            return_code=$?

            if [ $return_code -eq 0 ]; then
                echo "Command executed successfully."
                break
            else
                echo "Error detected! Retrying..."
                sleep 1
            fi
        done
        
        echo -e "\Starting udhcpc..."
        sudo udhcpc -q -f -n -i $INTERFACE

        echo -e "\nFinished connect to network."
        exit 0
    else
        echo -e "\nUnknown modem type: "$MODEM
        echo "Recognized modems: v2, microhard, doodle, quectel, microhard, em9191"
        exit 0
    fi

elif [ $PLATFORM == "apq8096" ]
then
    echo -e "\napq8096 detected..."

    if [ $MODEM == "v1" ]
    then
        echo -e "\nInitializing v1 modem..."
        voxl-modem --feather_configure

        echo -e "\nWaiting for ttyACM0..."
        rc=1
        while [ $rc -ne 0 ]; do
            ls /dev | grep ttyACM0
            rc=$?
            sleep 1
        done

        echo -e "\nSetting network preference to LTE"                                     
        uqmi -P -d /dev/qcqmi0 --set-network-preference lte
        echo -e "\nFinished setting network preference" 

        if [ $WORLD != "true" ]
        then
            echo -e "Disabling band 5..."
            configband write /dev/ttyUSB0 0x80a
        fi
    
        # Loop forever trying to get the cellular link up.
        echo -e "\nInitalizing cellular connection..."
        rc=1
        while [ $rc -ne 0 ]; do
            voxl-modem --connect_to_network
            rc=$?
            if [[ $rc -eq 0 ]]; then
                echo -e "\nCellular connection complete."
                exit $rc
            fi
            sleep 1
        done

    elif [ $MODEM == "v2" ]
    then
        echo -e "\nInitializing v2 modem..."
        enable-sierra.sh &> /dev/null

        rc=1
        echo -e "\nWaiting for ttyUSB2..."
        while [ $rc -ne 0 ]; do
            ls /dev | grep ttyUSB2
            rc=$?
            sleep 1
        done

        enable-dns.sh

        # Loop forever trying to get the cellular link up.
        echo -e "\nInitalizing cellular connection..."
        rc=1
        while [ $rc -ne 0 ]; do
            sierra.py
            rc=$?
            if [[ $rc -eq 0 ]]; then
                echo -e "\nCellular connection complete."
                exit $rc
            fi
            sleep 1
        done

    elif [ $MODEM == "microhard" ]
    then
        echo -e "\nInitializing Microhard modem..."
        voxl-modem --microhard_configure
    elif [ $MODEM == "doodle" ]
    then
        echo -e "\nWaiting for eth0..."
        rc=1
        while [ $rc -ne 0 ]; do
            ifconfig -a | grep eth0
            rc=$?
            sleep 1
        done

        echo -e "\neth0 initialized"

        # loop and re-set IP if network interface goes down and back up
        while true
        do
            # grab ip address from eth0
            eth0_ip=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)

            # if it's not what we expect, fix it
            if [[ "$eth0_ip" != *"$DOODLE_IP"* ]]; then
                echo "setting IP address to: $DOODLE_IP"
                ifconfig eth0 $DOODLE_IP netmask 255.0.0.0 up
            fi
            sleep 1
        done

    elif [ $MODEM == "quectel" ]
    then
        echo -e "\nInitializing Quectel modem..."

        echo -e "\nWaiting for ttyUSB2..."
        rc=1
        while [ $rc -ne 0 ]; do
            ls /dev | grep ttyUSB2
            rc=$?
            sleep 1
        done

        enable-dns.sh

        # set mode pref to LTE / 5G
        echo -ne "AT+QNWPREFCFG=\"mode_pref\",LTE:NR5G\r" | busybox microcom -t 1000 /dev/ttyUSB2

        # Loop forever trying to get the cellular link up.
        echo -e "\nInitalizing cellular connection..."
        loop=1
        while [ $loop -ne 0 ]; do
            quectel-CM -s $APN
        done

    else
        echo -e "\nUnknown modem type: "$MODEM
        echo "Recognized modems: v1, v2, microhard, doodle"
        exit 0
    fi
else
    echo -e "[ERROR] Platform not recognized: "$PLATFORM
    exit 5
fi
