#!/bin/bash

# read tmp path
TMP_PATH=$(head -n 1 cfg/tmp_path)

# read version
VERSION=$(head -n 1 version)

# install dependencies?
INSTALL_DEPENDENCIES=$(head -n 1 cfg/install_dependencies)
if [ "${INSTALL_DEPENDENCIES}" == true ] ; then
    read -p "Do you want to install dependencies(y/Y)? " -n 1 -r
    printf '%s\n'    # (optional) move to a new line
    if [[ $REPLY =~ ^[Yy]$ ]]
    then
        printf '%s\n' "-------------------------------------------"
        ${TERMINAL} ./install_dependencies.sh
        printf '%s\n' "-------------------------------------------"
    else
        read -p "Please install dependencies by hand as described in the documentation, cfg/install_dependencies will be set to false"
    fi
    printf '%s\n' "false" > cfg/install_dependencies
fi 
        
# first remove previous temporary working folder
if [ -d "${HOME}${TMP_PATH}" ]; then
    rm -r "${HOME}${TMP_PATH}"
fi

# create new temporary working folder
mkdir -p "${HOME}${TMP_PATH}"

# copy files to tmp path
cp -r "./cfg" "${HOME}${TMP_PATH}"
cp -r "./state" "${HOME}${TMP_PATH}"
cp -r "./tmp" "${HOME}${TMP_PATH}"

# read configuration from files copied in tmp path
BAUD=$(head -n 1 ${HOME}${TMP_PATH}/cfg/baud)
SYNCBYTE=$(head -n 1 ${HOME}${TMP_PATH}/cfg/syncbyte)
CONFIDENCE=$(head -n 1 ${HOME}${TMP_PATH}/cfg/confidence)
LIMIT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/limit)
TERMINAL=$(head -n 1 ${HOME}${TMP_PATH}/cfg/terminal)
PROBE_MSG=$(head -n 1 ${HOME}${TMP_PATH}/cfg/probe_msg)
PROBE_SLEEP=$(head -n 1 ${HOME}${TMP_PATH}/cfg/probe_sleep)
HALF_DUPLEX=$(head -n 1 ${HOME}${TMP_PATH}/cfg/half_duplex)
VOLUME_SPEAKER_LEFT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/volume_speaker_left)
VOLUME_SPEAKER_RIGHT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/volume_speaker_right)
VOLUME_MICROPHONE=$(head -n 1 ${HOME}${TMP_PATH}/cfg/volume_microphone)
TEXT_TO_SPEECH=$(head -n 1 ${HOME}${TMP_PATH}/cfg/text_to_speech)
SPEECH_TO_TEXT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/speech_to_text)
INTERFACE_INDEX_TTS_OUT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/interface_index_tts_out)
INTERFACE_INDEX_STT_IN=$(head -n 1 ${HOME}${TMP_PATH}/cfg/interface_index_stt_in)
INTERFACE_INDEX_MINIMODEM_OUT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/interface_index_minimodem_out)
INTERFACE_INDEX_MINIMODEM_IN=$(head -n 1 ${HOME}${TMP_PATH}/cfg/interface_index_minimodem_in)
VOLUME_STT_IN=$(head -n 1 ${HOME}${TMP_PATH}/cfg/volume_stt_in)
VOLUME_TTS_OUT=$(head -n 1 ${HOME}${TMP_PATH}/cfg/volume_tts_out)
LLM_CMD=$(head -n 1 ${HOME}${TMP_PATH}/cfg/llm_cmd)

# SET_COMM_IFS
# WORKAROUND: for now, clear audio interfaces for communication in case they were set although not yet supported
if [ "${INTERFACE_INDEX_MINIMODEM_IN}" != "" ] ; then
    printf "INTERFACE_INDEX_MINIMODEM_IN is not supported yet. The default audio interfaces will be used instead."
    INTERFACE_INDEX_MINIMODEM_IN=
fi
if [ "${INTERFACE_INDEX_MINIMODEM_OUT}" != "" ] ; then
    printf "INTERFACE_INDEX_MINIMODEM_OUT is not supported yet. The default audio interfaces will be used instead."
    INTERFACE_INDEX_MINIMODEM_OUT=
fi

trap ctrl_c INT
function ctrl_c()
{
    # TODO: kill child/started processes before ctrl-c
    # kill $(ps -s $$ -o pid=)
    # pkill -P $$
    # restore mic volume
    ${TERMINAL} ./restore_audio_settings.sh  # &
    # TODO: brute-force kill?
    # Disable mouse + reset (in case tmux was config. with mouse)
    # otherwise we may get strange characters in the terminal after Ctrl+C
    printf '\033[?1000l\033[?1002l\033[?1006l\033c'
    tmux kill-server 2>/dev/null || true
    stty sane 2>/dev/null || true
    ./killtea2adt.sh 2> /dev/null  # &
    # and now ctrl-c
    trap - INT
    kill -INT $$
}

# SET_COMM_IFS
set_interfaces()
{
    # speaker / sink (communication)
    if [ "${INTERFACE_INDEX_MINIMODEM_OUT}" != "" ] ; then
        # get sink-input
        while true; do
            SINK_INPUT=$(pacmd list-sink-inputs | awk '/index:/{idx=$2} /application.process.binary = "minimodem"/{print idx; exit}')
            if [ -n "$SINK_INPUT" ]; then
                break
            fi
            sleep 1
        done
        # set configured sink for this specific sink-input
        pactl move-sink-input ${SINK_INPUT} ${INTERFACE_INDEX_MINIMODEM_OUT}
        printf '%s\n' "set minimodem output with sink input ${SINK_INPUT} to interface index ${INTERFACE_INDEX_MINIMODEM_OUT}"
    fi
    # microphone / source (communication)
    if [ "${INTERFACE_INDEX_MINIMODEM_IN}" != "" ] ; then
        # get source-input
        while true; do
            SOURCE_OUTPUT=$(pacmd list-source-outputs | awk '/index:/{idx=$2} /application.process.binary = "minimodem"/{print idx; exit}')
            if [ -n "$SOURCE_OUTPUT" ]; then
                break
            fi
            sleep 1
        done
        # set configured source for this specific source-output
        pactl move-source-output ${SOURCE_OUTPUT} ${INTERFACE_INDEX_MINIMODEM_IN}
        printf '%s\n' "set minimodem input with source output ${SOURCE_OUTPUT} to interface index ${INTERFACE_INDEX_MINIMODEM_IN}"
    fi
}

set_volumes()
{
    # termux
    # pactl sets later the volume at the PulseAudio/software level,
    # essentially a multiplier applied within PulseAudio, on top of Android's hardware stream level
    # so we need to also set Android's volume
    if [ -n "$TERMUX_VERSION" ] || [[ "$PREFIX" == *"com.termux"* ]]; then
        if command -v termux-volume &> /dev/null; then
            # TODO: add config. value for termux-volume (0-15), for now hardcoded
            termux-volume music 10
            printf '%s\n' "Termux version "$TERMUX_VERSION" detected"
        else
            printf '%s\n' "Termux detected but termux-volume not found (install termux-api)"
        fi
    fi
    # speaker
    if [ "${INTERFACE_INDEX_MINIMODEM_OUT}" != "" ] ; then
        if [ "${VOLUME_SPEAKER_LEFT}" != "" ] ; then
            pactl -- set-sink-volume ${INTERFACE_INDEX_MINIMODEM_OUT} ${VOLUME_SPEAKER_LEFT} ${VOLUME_SPEAKER_RIGHT}
            printf '%s\n' "setting output/speaker volume to L,R = ${VOLUME_SPEAKER_LEFT},${VOLUME_SPEAKER_RIGHT}"
        fi
        printf '%s\n' "configured output/speaker, index = " ${INTERFACE_INDEX_MINIMODEM_OUT}
    else
        if [ "${VOLUME_SPEAKER_LEFT}" != "" ] ; then
            default_sink_index=$(pacmd list-sinks | grep "* index: " | grep -o '...$')
            if [ "${default_sink_index:0:1}" == ":" ] ; then
                 default_sink_index=$(pacmd list-sinks | grep "* index: " | grep -o '..$')
            fi
            pactl -- set-sink-volume ${default_sink_index} ${VOLUME_SPEAKER_LEFT} ${VOLUME_SPEAKER_RIGHT}
            printf '%s\n' "setting default output/speaker volume to L,R = "${VOLUME_SPEAKER_LEFT}","${VOLUME_SPEAKER_RIGHT}
            # printf '%s\n' "(leave cfg/volume_speaker_left empty in order to not set input volume automtatically)"
        fi
        # printf '%s\n' default settings for communication
        printf '%s\n' "default output/speaker, index = " ${default_sink_index}
    fi
    # mic
    if [ "${INTERFACE_INDEX_MINIMODEM_IN}" != "" ] ; then
        if [ "${VOLUME_MICROPHONE}" != "" ] ; then   
            pactl -- set-source-volume ${INTERFACE_INDEX_MINIMODEM_IN} ${VOLUME_MICROPHONE}
            printf '%s\n' "setting input/microphone volume to "${VOLUME_MICROPHONE}
            # printf '%s\n' "(leave cfg/volume_microphone empty in order to not set output volume automtatically)"
        fi
        printf '%s\n' "configured input/microphone, index = " ${INTERFACE_INDEX_MINIMODEM_IN}
    else
        if [ "${VOLUME_MICROPHONE}" != "" ] ; then
            default_source_index=$(pacmd list-sources | grep "* index: " | grep -o '...$')
            if [ "${default_source_index:0:1}" == ":" ] ; then
                 default_source_index=$(pacmd list-sources | grep "* index: " | grep -o '..$')
            fi    
            pactl -- set-source-volume ${default_source_index} ${VOLUME_MICROPHONE}
            printf '%s\n' "setting input/microphone volume to "${VOLUME_MICROPHONE}
            # printf '%s\n' "(leave cfg/volume_microphone empty in order to not set output volume automatically)"
        fi
        printf '%s\n' "default input/microphone, index = " ${default_source_index}
    fi
    # TTS
    if [ "${TEXT_TO_SPEECH}" != "" ] ; then
        if [ "${VOLUME_TTS_OUT}" != "" ] ; then
            pactl -- set-sink-volume ${INTERFACE_INDEX_TTS_OUT} ${VOLUME_TTS_OUT}
            printf '%s\n' "setting TTS output/speaker volume = "${VOLUME_TTS_OUT}
        fi
    fi
    # STT
    if [ "${SPEECH_TO_TEXT}" == true ] ; then
        if [ "${VOLUME_STT_IN}" != "" ] ; then
            pactl -- set-source-volume ${INTERFACE_INDEX_STT_IN} ${VOLUME_STT_IN}
            printf '%s\n' "setting STT input/microphone volume = "${VOLUME_STT_IN}
        fi
    fi
    # echo TTS and STT settings
    printf '%s\n' "TTS command = "${TEXT_TO_SPEECH}
    printf '%s\n' "TTS output/speaker, index = "${INTERFACE_INDEX_TTS_OUT}
    printf '%s\n' "STT input/microphone, index = "${INTERFACE_INDEX_STT_IN}
}

create_fifos()
{
    if [ "$1" == "-l" ] || [ "$1" == "--llm" ] || [ "$1" == "--llm-chat" ] || [ "$1" == "--llm-prompt" ] ; then
        PIPE_LLM_OUT="${HOME}${TMP_PATH}/tmp/pipe_llm_out"
        if [ -p ${PIPE_LLM_OUT} ] || [ -f ${PIPE_LLM_OUT} ]; then
          rm ${PIPE_LLM_OUT}
        fi
        mkfifo ${PIPE_LLM_OUT}
    elif [ "$1" == "-s" ] || [ "$1" == "--rs" ] || [ "$1" == "--remote-shell" ] || [ "$1" == "--reverse-shell" ] ; then
        PIPE_SHELL_IN="${HOME}${TMP_PATH}/tmp/pipe_shell_in"
        PIPE_SHELL_OUT="${HOME}${TMP_PATH}/tmp/pipe_shell_out"
        if [ -p ${PIPE_SHELL_IN} ] || [ -f ${PIPE_SHELL_IN} ]; then
          rm ${PIPE_SHELL_IN}
        fi
        if [ -p ${PIPE_SHELL_OUT} ] || [ -f ${PIPE_SHELL_OUT} ]; then
          rm ${PIPE_SHELL_OUT}
        fi
        mkfifo ${PIPE_SHELL_IN}
        mkfifo ${PIPE_SHELL_OUT}
    elif [ "$1" == "-f" ] || [ "$1" == "--file" ] ; then
        PIPE_FILE_IN="${HOME}${TMP_PATH}/tmp/pipe_file_in"
        PIPE_FILE_OUT="${HOME}${TMP_PATH}/tmp/pipe_file_out"
        if [ -p ${PIPE_FILE_IN} ] || [ -f ${PIPE_FILE_IN} ]; then
          rm ${PIPE_FILE_IN}
        fi
        if [ -p ${PIPE_FILE_OUT} ] || [ -f ${PIPE_FILE_OUT} ]; then
          rm ${PIPE_FILE_OUT}
        fi
        mkfifo ${PIPE_FILE_IN}
        mkfifo ${PIPE_FILE_OUT}
    fi
}

ask_password()
{
    while true
    do
        while true
        do
            printf '%s' "password: "
            read -ers PASSWORD1
            printf '%s\n' ""
            # 2> /dev/null shall prevent showing the password if some error occurs
            if [ ! "${PASSWORD1}" == "" ] 2> /dev/null
            then
                break
            else
                printf '%s\n' "Password cannot be empty!"
            fi
        done
        printf '%s' "confirm password: "
        read -ers PASSWORD
        printf '%s\n' ""
        # 2> /dev/null shall prevent showing the password if some error occurs
        [ "${PASSWORD1}" == "${PASSWORD}" ] 2> /dev/null && break
        printf '%s\n' "Passwords dont match!"
    done
}

# SET_COMM_IFS
# TODO: if we get feature # SET_COMM_IFS to work, then we need to update this function to show the correct comm. interfaces
#       which will then be defined by INTERFACE_INDEX_MINIMODEM_IN and INTERFACE_INDEX_MINIMODEM_OUT
echo_audio_interfaces()
{
    # list audio output interfaces
    printf '%s\n' "audio output interfaces"
    printf '%s\n' "-----------------------"
    printf '%s\n' "$(pactl list short sinks)"
    # list audio input interfaces
    printf '%s\n' ""
    printf '%s\n' "audio input interfaces"
    printf '%s\n' "----------------------"
    printf '%s\n' "$(pactl list short sources)"
    # default audio output / speaker
    default_sink_index=$(pacmd list-sinks | grep "* index: " | grep -o '...$')
    if [ "${default_sink_index:0:1}" == ":" ] ; then
         default_sink_index=$(pacmd list-sinks | grep "* index: " | grep -o '..$')
    fi
    # default audio input / mic
    default_source_index=$(pacmd list-sources | grep "* index: " | grep -o '...$')
    if [ "${default_source_index:0:1}" == ":" ] ; then
         default_source_index=$(pacmd list-sources | grep "* index: " | grep -o '..$')
    fi
    # echo settings
    printf '%s\n' ""
    printf '%s\n' "audio settings for communication"
    printf '%s\n' "--------------------------------"
    printf '%s\n' "default output/speaker, index = " ${default_sink_index}
    printf '%s\n' "default input/microphone, index = " ${default_source_index}
    printf '%s\n' ""
    printf '%s\n' "audio settings for TTS and STT"
    printf '%s\n' "--------------------------------"
    printf '%s\n' "TTS output/speaker, index = " ${INTERFACE_INDEX_TTS_OUT}
    printf '%s\n' "STT input/microphone, index = " ${INTERFACE_INDEX_STT_IN}
    printf '%s\n' ""
}

echo_help()
{
    printf '%s\n' "usage: tea2adt [-c|-s]
    		 -c, --chat
    		 -l, --llm, --llm-chat, --llm-prompt
    		 -s, --rs, --remote-shell, --reverse-shell (to execute a command as sudo type: echo \"<pwd>\" | sudo -k -S <cmd>)
    		 -f, --file, --file-transfer
    		 -p, --probe (send periodic test messages to check connectivity and adjust the volumes if required)
    		 -g, --gui (only for configuration)
    		 -a, --audio-settings
    		 -d, --directory (show installation path)
    		 -V, --version
    		 -h, --help
    		 -i, --image
    		 
tea2adt is a command-line utility for Chat, Remote Shell, Remote AI Prompt and File Transfer, that reads and writes encrypted data across peer-to-peer or broadcast audio connections, using minimodem and gpg.
It is a powerful tool that can be combined with any audio infrastructure (like PSTN, cellular network, internet, radio) to provide a secure communication channel through an audio tunnel.
The audio interfaces behave like data-diodes, each allowing unidirectional data transmission only, thus preventing data-leaks and malware-injection.
This enables an enhanced-end-to-end encryption (E-E2EE) which notably increases security and privacy, especially when the end devices are completely offline (air-gapped-system), providing an effective barrier against legal or illegal client-side-scanning!
Homepage: https://github.com/ClarkFieseln/tea2adt"
}

echo_image()
{
    printf '%s\n' "
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓█░█▓▓▓▓▓▓▓▓▓▓███░▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓█░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓█░░█▓▓▓▓▓▓▓▓▓▓███████▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▒█░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▒░░░▓█▓▓▓▓▓▓▓▓▓███████░██▓█▓▓▓▓▓▓▓▓▓█░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓█▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓█░░░▓███████████████████░██░░░░░░░░░█░░░░▓▓▓▓▓▓▓█▓▓▓▓█▓▓▓▓█▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▒░░░██▓▓▓▓▓▓▓▓▓██████▒█▒▓▓█▓▓▓▓▓▓▓▓▓██░░░▓▓▓▓▓▓▓▓█▓▓█▓▓▓▓▓▓▓▓█▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓█░░█▓▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▒█░█▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓██▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒██▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓░░▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▒░█▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▒█░██▒▓▓▓▓▓▓▓▓▓▓▓░░█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░██▓▓▓▓▓▓▓▓▓█▓▓▓█░░█████▓▓▓▓▓▓▓▓▓░█░░░█▓▓▓▓▓▓▓▓██▓▓▓▓█▓█▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░█▒░░░░░░░░░██░░██████████████████░░░░█▓▓▓▓▓███▓█▓███▓▓█▓▓▓██▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░█▒▓▓▓▓▓▓▓▓▓█▓▓█████████▓▓▓▓▓▓▓▓▓▓▒░░░█▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓█▓█▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▒░▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▒██████▓▓▓▓▓▓▓▓▓▓▓░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓░█▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓░█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
"
}

echo_parameters()
{
    printf '%s\n' "baud = $BAUD"
    printf '%s\n' "half_duplex = $HALF_DUPLEX"
    printf '%s\n' "syncbyte = $SYNCBYTE"
    printf '%s\n' "confidence = $CONFIDENCE"
    printf '%s\n' "limit = $LIMIT"
    printf '%s\n' "terminal = $TERMINAL"
    printf '%s\n' "volume speaker left = $VOLUME_SPEAKER_LEFT"
    printf '%s\n' "volume speaker right = $VOLUME_SPEAKER_RIGHT"
    printf '%s\n' "volume microphone = $VOLUME_MICROPHONE"
    printf '%s\n' "text to speech = $TEXT_TO_SPEECH"
    printf '%s\n' "speech to text = $SPEECH_TO_TEXT"
    printf '%s\n' "volume TTS out = $VOLUME_TTS_OUT"
    printf '%s\n' "volume STT in = $VOLUME_STT_IN"
}

echo_version()
{
    printf '%s\n' "tea2adt ${VERSION}
MIT License: <https://opensource.org/license/mit>.    
Copyright (C) 2026 Clark Fieseln
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law."
}

: '
# SET_COMM_IFS
---------------------------------------------
NOTE: set audio interfaces for communication:
---------------------------------------------
    in the tested solution minimodem is running in a background tmux session (or a screen session) with a pipe to cat | minimodem
    (in that case the sink-source remains always the same, i.e. interface_index_minimodem_in/out are set once and are working as expected)
    but in that case the communication gets very unstable due to synchronization issues in minimodem, and probably also due to buffering in pipe, cat or tmux/screen
    alternatives using a named pipe instead of cat, or a temporary variable or file did not work as minimodem gets called several times
    A "dynamic" solution which detects the current sink-source used by minimodem which each call was not implemented
    because it may bring timing-problems as is the case when setting the TTS sink based on the sink-input
    A generic solution using virtual sinks and load-module in pulse audio may also not work when the sink-input changes with each call to minimodem.
init_minimodem()
{
    # init minimodem process in new tmux session which can then be written with tmux send-keys -t session_mmtx
    tmux new-session -d -s session_mmtx "cat | minimodem --tx --ascii --quiet --startbits 1 --stopbits 1.0 --sync-byte ${SYNCBYTE} --volume 1.0 ${BAUD}" &
    # alternative:
    # screen -dmS session_mmtx bash -c "cat | minimodem --tx --ascii --quiet --startbits 1 --stopbits 1.0 --sync-byte 0x7F --volume 1.0 9600" &
}
'

# options
if [ "$1" == "" ] ; then
    printf '%s\n' "tea2adt: you must specify an option, run tea2adt -h for more information"
    echo_help
elif [ "$1" == "-a" ] || [ "$1" == "--audio-settings" ] ; then  
    echo_audio_interfaces
elif [ "$1" == "-c" ] || [ "$1" == "--chat" ] ; then
    ask_password
    # init_minimodem
    set_volumes
    create_fifos "$1"
    ${TERMINAL} ./mmtx.sh "${PASSWORD}" &
    # wait a little bit so the transmitter can initialize the state flags
    sleep 0.5
    echo_parameters
    # don't call set_interfaces here, have not yet a source-output, need yet to run rx.src
    source rx.src | python3 mmrx.py "${PASSWORD}" $1
elif [ "$1" == "-f" ] || [ "$1" == "--file" ] ; then
    ask_password
    # init_minimodem
    set_volumes
    create_fifos "$1"
    ${TERMINAL} ./mmtxfile.sh "${PASSWORD}" &
    # wait a little bit so the transmitter can initialize the state flags
    sleep 0.5
    # track input files
    ${TERMINAL} cat ${PIPE_FILE_IN} &
    # don't call set_interfaces here, have not yet a source-output, need yet to run rx.src
    # we don't echo_parameters in -f mode
    source rx.src | python3 mmrx.py "${PASSWORD}" $1
elif [ "$1" == "-l" ] || [ "$1" == "--llm" ] || [ "$1" == "--llm-chat" ] || [ "$1" == "--llm-prompt" ] ; then
    ask_password
    # init_minimodem
    set_volumes
    create_fifos "$1"
    if [ "${LLM_CMD}" != "" ] ; then
        # check if ollama is used and if it is running
        if [[ ${LLM_CMD} =~ "ollama run" ]]; then
            while ! curl -s http://localhost:11434/api/tags > /dev/null; do
                # sleep 1
                printf '%s\n' "Error: ollama is not running!"
                exit
            done
        fi
        # create persistent session to run in background with output pipe
        # (input is done with command 'tmux send-keys -t session_llm')
        tmux new-session -d -s session_llm "${LLM_CMD} > ${PIPE_LLM_OUT}" &
        # TODO: use instead 2> to not redirect errors?
        #       tmux new-session -d -s session_llm "${LLM_CMD} 2> ${PIPE_LLM_OUT}" &
        printf '%s\n' "LLM model started..."
    else
        printf '%s\n' "Error: llm_cmd is not configured!"
        exit
    fi
    echo_parameters
    # don't call set_interfaces here, have not yet a source-output, need yet to run rx.src
    source rx.src | python3 mmrx.py "${PASSWORD}" $1
elif [ "$1" == "-s" ] || [ "$1" == "--rs" ] || [ "$1" == "--remote-shell" ] || [ "$1" == "--reverse-shell" ] ; then
    ask_password
    # init_minimodem
    set_volumes
    create_fifos "$1"
    # create persistent shell to run in background with input and output pipes
    while true; do /bin/sh &> ${PIPE_SHELL_OUT}; done 0< ${PIPE_SHELL_IN} &
    echo_parameters
    # don't call set_interfaces here, have not yet a source-output, need yet to run rx.src
    source rx.src | python3 mmrx.py "${PASSWORD}" $1
elif [ "$1" == "-p" ] || [ "$1" == "--probe" ] ; then
    # init_minimodem
    set_volumes
    echo_parameters
    ${TERMINAL} ./mmrxnopwd.sh &
    printf '%s\n' "**********************************"
    printf '%s\n' "*** tea2adt probe transmitter ****"
    printf '%s\n' "**********************************"
    printf '%s\n' "Test messages "${PROBE_MSG}" sent with a delay of "${PROBE_SLEEP}" seconds..."
    printf '%s\n' "(a separate terminal is opened to receive unencrypted test messages from the communication partner)"
    # SET_COMM_IFS
    # set_interfaces
    while :
    do
        printf '%s\n' "${PROBE_MSG}" | source tx.src
        sleep ${PROBE_SLEEP}
    done
elif [ "$1" == "-g" ] || [ "$1" == "--gui" ] ; then
    python3 gui.py
elif [ "$1" == "-d" ] || [ "$1" == "--directory" ] ; then
    printf '%s\n' $(pip show tea2adt | grep Location)"/tea2adt_source"
elif [ "$1" == "-V" ] || [ "$1" == "--version" ] ; then
    echo_version
elif [ "$1" == "-h" ] || [ "$1" == "--help" ] ; then
    echo_help
elif [ "$1" == "-i" ] || [ "$1" == "--image" ] ; then
    echo_image  
else
    printf '%s\n' "tea2adt: invalid option"
fi
