#!/usr/bin/env bash

VERSION=3.1.1
red='\033[1;31m'
green='\033[1;32m'
yellow='\033[1;33m'
blue='\033[1;34m'
light_cyan='\033[1;96m'
reset='\033[0m'

WINKEXDIR="/usr/lib/win-kex"
XSTARTUP="${WINKEXDIR}/xstartup"
XRDPINI="/etc/xrdp/xrdp.ini"
XRDPSERVICE="${WINKEXDIR}/xrdp/xrdpservice"
XSERV="${WINKEXDIR}/VcXsrv/vcxsrv.exe"
XSERVSESSION=3
VNCSRV=$(which tigervncserver)
VNCCLIENT="${WINKEXDIR}/TigerVNC/win-kex-win-x64"
SESSION_CACHE="${HOME}/.cache/sessions/xfce4-session-"
WSLGSOCK="${WINKEXDIR}/wslg-sock/wslg-sock"
HOST="localhost"
## Alt:  awk '/nameserver/ {print $2; exit}' /etc/resolv.conf
##       /sbin/ip route | awk '/default/ {print $3}'
#HOSTIP=$(grep -m 1 nameserver /etc/resolv.conf | awk '{print $2}')
# HOSTIP=$(route.exe print | grep 0.0.0.0 | head -1 | awk '{print $4}')
HOSTIP=$(grep -m 1 nameserver /etc/resolve.conf | awk '{print $2}')
RECONN_ON_ERR=1
VERBOSE=
NOWGL=
ARCH=$(uname -m)
SLTIMEOUT=100
unset IP USR SOUND MULTISCREEN

function print-help() {
    printf "\n\tWin-KeX provides a GUI desktop experience for Snigdha OS in Windows Subsystem for Linux (WSL 2)"
    printf "\n"
    printf "\n\tUsage:"
    printf "\n\t\tkex <mode> <command> <parameters>"
    printf "\n"
    printf "\n\t\t${blue}Mode:${reset}"
    printf "\n\t\t[none]\t\t : Window Mode (default)"
    printf "\n\t\t--esm\t\t : Enhanced Session Mode - Launch Win-KeX desktop in a dedicated window using Windows native RDP"
    printf "\n\t\t--sl\t\t : SeamLess mode - Seamlessly integrate Win-KeX into the Windows desktop"
    printf "\n\t\t--win\t\t : WINdow mode - Launch Win-KeX desktop in a dedicated window"
    printf "\n"
    printf "\n\t\t${blue}Command:${reset}"
    printf "\n\t\t[none]\t\t : Start Win-KeX server and launch Win-KeX client"
    printf "\n\t\t--start\t\t : Start Win-KeX server"
    printf "\n\t\t--start-client\t : Start Win-KeX client"
    printf "\n\t\t--wtstart\t : Start Win-KeX server and launch Win-KeX client in Windows Terminal session"
    printf "\n\t\t--stop\t\t : Stop Win-KeX server"
    printf "\n\t\t--status\t : Show Win-KeX server status"
    printf "\n\t\t--kill\t\t : Stop Win-KeX server and kill all related processes"
    printf "\n\t\t--passwd\t : Set Win-KeX server password"
    printf "\n\t\t--start-sound\t : Start Windows sound server"
    printf "\n\t\t--stop-sound\t : Stop Windows sound server"
    printf "\n\t\t--wslg-restore\t : Restore WSLg unix socket"
    printf "\n\t\t--wslg-remove\t : Remove WSLg unix socket"
    printf "\n\t\t--wslg-status\t : Display status of WSLg unix socket"
    printf "\n\t\t--version\t : Display Win-KeX version"
    printf "\n\t\t--help\t\t : Display this help"
    printf "\n"
    printf "\n\t\t${blue}(Optional) Parameters:${reset}"
    printf "\n\t\t--ip \t\t-i : Use container IP address instead of \"localhost\""
    printf "\n\t\t--multiscreen \t-m : Optimized for multiscreen"
    printf "\n\t\t--sound \t-s : Sound support"
    printf "\n\t\t--nowgl \t-n : Disable Windows OpenGL"
    printf "\n\t\t--norc \t\t-r : Disable Win-KeX client reconnecting - once is enough!"
    printf "\n\t\t--wait \t\t-w : Wait longer for desktop to start when in SL mode"
    printf "\n\t\t--use-existing-gui-vars \t\t : Use existing DISPLAY and PULSE_SERVER variables, without changing. Useful if you have a custom setup outside of KeX or want to use WSLG."
    printf "\n\t\t--verbose\t   : Verbose output"
    printf "\n"
    printf "\n\tExamples:"
    printf "\n\t\tkex -s\t\t : Start Win-KeX server in window mode and launch Win-KeX client with sound support"
    printf "\n\t\tkex --sl -s\t : Start Win-KeX in seamless mode and launch Win-KeX client with sound support"
    printf "\n\t\tkex --esm -i -s\t : Start Win-KeX in Enhanced Session Mode with ARM workaround and launch Win-KeX client with sound support"
    printf "\n\t\tsudo kex\t : Start Win-KeX server as root in window mode and launch Win-KeX client"
    printf "\n"
}

function print-verbose() {
    if [ -n "${VERBOSE}" ]; then
        printf "> $@\n"
    fi
}

function print-version() {
    printf "$0: ${VERSION}\n"
}

function print-wrong-arch() {
    printf "\n\t${light_cyan}The function is not supported on this architecture${SESSION_FILE}${reset}\n"
}

function ask() {
    # http://djm.me/ask
    while true; do
        if [ "${2:-}" = "Y" ]; then
            prompt="Y/n"
            default=Y
        elif [ "${2:-}" = "N" ]; then
            prompt="y/N"
            default=N
        else
            prompt="y/n"
            default=
        fi

        # Ask the question
        printf "${light_cyan}$1"
        read -p " [${prompt}] " REPLY

        # Default?
        if [ -z "${REPLY}" ]; then
            REPLY=${default}
        fi

        printf "${reset}"

        # Check if the reply is valid
        case "${REPLY}" in
            Y*|y*) return 0 ;;
            *)     return 1 ;;
        esac
    done
}

function is-root() {
    print-verbose "Checking account type"
    if [ -z ${USR} ]; then
        USR=$(whoami)
    fi

    if [ "${USR}" == "root" ]; then
        print-verbose "Root user"
        # 0 = true
        return 0
    else
        print-verbose "Non-root user"
        # 1 = false
        return 1
    fi
}

function sudo-active() {
    print-verbose "Checking sudo"
    if sudo -nv 2>/dev/null; then
        print-verbose "Found sudo"
        # 0 = true
        return 0
    else
        print-verbose "Without sudo"
        # 1 = false
        return 1
    fi
}

function wslg-socket-check() {
    print-verbose "Checking for WSLg socket"
    if [ -L /tmp/.X11-unix ]; then
        print-verbose "Found existing WSLg socket (Bad)"
        # 0 = true
        return 0
    else
        print-verbose "Missing socket (Good)"
        # 1 = false
        return 1
    fi
}

function wslg-socket-remove(){
    print-verbose "Converting WSLg socket to Win-KeX"
    #printf "\n\t${red}A WSLg socket exists that prevent Win-KeX from starting${reset}"
    #printf "\n\t${red}Removing the socket now. This will not adversely affect WSL or Win-KeX${reset}\n"
    sudo ${WSLGSOCK} remove
    return $?
}

function wslg-socket-restore(){
    print-verbose "Restoring WSLg socket"
    sudo ${WSLGSOCK} restore
    return $?
}

function wslg-socket-status(){
    status=$(${WSLGSOCK} status)
    result=$?
    if [ "${result}" != "0" ]; then
        printf "\t${green}${status}${reset}\n"
    else
        printf "\t${red}${status}${reset}\n"
    fi
    return ${result}
}

function start-kex-win() {
    printf 'Starting Win-KeX server (Win)\n'
    if wslg-socket-check; then
        wslg-socket-remove
    fi

    # if [ ! -f ~/.config/tigervnc/passwd ]; then
    #     passwd-set-win
    # fi

    if [ ! -f ~/.vnc/passwd ]; then
        passwd-set-win
    fi

    if is-root; then
        SCREEN=":2"
    else
        SCREEN=":1"
    fi

    if ! grep -q "$SCREEN=$USER" "/etc/tigervnc/vncserver.users"; then
        echo "$SCREEN=$USER" | sudo tee -a /etc/tigervnc/vncserver.users
    fi

    if [ -z ${SOUND} ]; then
        print-verbose "Skipping sound support"
        unset PULSE_SERVER
    else
        print-verbose "Sound support requested"
        export PULSE_SERVER=tcp:${HOSTIP}
        # if [ -z "$PULSE_SERVER" ] || [ "${USE_EXISTING_GUI_VARS}" != 1 ]; then
        #     export PULSE_SERVER=tcp:${HOSTIP}
        # fi
    fi

    ## REF: https://github.com/microsoft/WSL/issues/9303
    if ! [ -w /tmp/.X11-unix ]; then
        print-verbose "/tmp/.X11-unix is mounted as read-only - attempting to re-mount"

        ## Clashes with wslg-socket-remove() / $ sudo ${WSLGSOCK} remove
        #sudo umount /tmp/.X11-unix
        #ln -sf /mnt/wslg/.X11-unix/X0 /tmp/.X11-unix/
        sudo mount -o remount,rw /tmp/.X11-unix

        if ! [ -w /tmp/.X11-unix ]; then
            printf "\n\t${red}/tmp/.X11-unix is still read-only${reset}\n"
            mount | grep /tmp/.X11-unix
        else
            print-verbose "Remount successful"
        fi
    fi

    print-verbose "Running Win-KeX server (Win)"
    # ${VNCSRV} -useold -xstartup ${XSTARTUP} -SecurityTypes=VeNCrypt,TLSVnc ${SCREEN} >/dev/null 2>&1 </dev/null
    sudo systemctl start vncserver@$SCREEN.sevice >/dev/null 2>&1 </dev/null
    result=$?

    if [ "${result}" != "0" ]; then
        print-verbose "${VNCSRV}: ${result}"
        print-verbose "Possible Win-KeX server (Win) did not start up correctly. Check logs: ~/.vnc/$(hostname).${SCREEN}.log"
    fi

    print-verbose "Win-KeX server (Win) started"
    starting_kex=1

    status-kex-win
    sessions-kex-win
    return 0
}

function stop-kex-win() {
    print-verbose "Stopping Win-KeX server (Win)"
    # taskkill.exe /IM win-kex-win-x64 /T /F >/dev/null 2>&1
    /init /mnt/c/Windows/system32/taskkill.exe taskkill.exe /IM win-kex-win-x64 /T /F >/dev/null 2>&1
    # local output_1=$(${VNCSRV} -kill :1 2>&1)
    # local output_2=$(${VNCSRV} -kill :2 2>&1)
    sudo systemctl stop vncserver@:1.sevice 2>&1
    sudo systemctl stop vncserver@:2.sevice 2>&1
    local output_1=$(systemctl is-active vncserver@:2.sevice 2>&1)
    local output_2=$(systemctl is-active vncserver@:2.sevice 2>&1)
    # sudo systemctl stop
    if [[ "${output_1}" == *"success!"* || "${output_2}" == *"success!"* ]]; then
        printf "\t${light_cyan}Win-KeX server (Win) stopped${reset}\n"
        return 0
    fi
    return 1
}

function start-kex-esm() {
    printf 'Starting Win-KeX server (ESM)\n'

    export DESKTOP="XFCE"
    sudo ${XRDPSERVICE} start
    status=$?

    print-verbose "Win-KeX server (ESM) started"
    status-kex-esm
    return ${status}
}

function stop-kex-esm() {
    print-verbose "Stopping Win-KeX server (ESM)"
    sudo ${XRDPSERVICE} stop
    if [ "$?" == "0" ]; then
        printf "\t${light_cyan}Win-KeX server (ESM) stopped${reset}\n"
        return 0
    fi
    return 1
}

function status-kex-esm(){
    ${XRDPSERVICE} status
    result=$?
    if [ "${result}" != "0" ]; then
        printf "\t${green}Win-KeX server (ESM) is running${reset}\n"
    else
        printf "\tWin-KeX server (ESM) is stopped\n"
    fi
    return ${result}
}

function sessions-kex-sl() {
    ## Workaround, as something has changed (WSL app? Linux packages?)
    ## This check if vcxsrv is pre-installed, and running on host (requires manual setup)
    ## - https://sourceforge.net/p/vcxsrv/wiki/VcXsrv%20%26%20Win10/
    ## - https://gist.github.com/alextsil/f8d861b8a2fc766c06aefc0c35c083ee
    vcxsrvhost=0
    timeout 3 bash -c "(echo > /dev/tcp/${HOSTIP}/6000)" >/dev/null 2>&1 \
        && vcxsrvhost=1
    if [ "${vcxsrvhost}" == "1" ]; then
        print-verbose "Found possible Win-KeX server (SL) running on host: ${HOSTIP}"
        XSERVSESSION=0 # means server host display on :0.0
        return 0
    else
        printf "\tUnable to find Win-KeX server (SL) running on host: ${HOSTIP}"
        print-verbose "Will try to use Win-KeX server (SL) inside of WSL"
        XSERVSESSION=3
        return 1
    fi
}

function start-kex-sl() {
    printf 'Starting Win-KeX server (SL)\n'
    if wslg-socket-check; then
        wslg-socket-remove
    fi

    if [ "${NOWGL}" == "1" ]; then
        print-verbose "Skipping Windows OpenGL support"
        wgl=""
    else
        print-verbose "Windows OpenGL support requested"
        wgl="-wgl"
    fi

    log="/tmp/win-kex-sl_$(whoami).log"
    print-verbose "Log file: ${log}"

    # if [ "${USE_EXISTING_GUI_VARS}" != 1 ]; then
    #     if ! sessions-kex-sl; then
    #         stop-kex-sl
    #         ${XSERV} :${XSERVSESSION} -ac -terminate ${XMULTIMONITORS} -logfile ${log} -logverbose 10 -multiwindow -lesspointer -clipboard ${wgl} >/dev/null 2>&1 &
    #         result=$?
    #         if [ "${result}" != "0" ]; then
    #             print-verbose "${XSERV}: ${result}"
    #             print-verbose "Possible Win-KeX server (SL) may not have been successful"
    #         fi
    #         status-kex-sl
    #     fi
    # fi
    if ! session-kex-sl; then
        stop-kex-sl
        /init /${XSERV} ${XSERV} :${XSERVSESSION} -ac -terminate ${XMULTIMONITORS} -logfile ${log} -logverbose 10 -multiwindow -lesspointer -clipboard ${wgl} >/dev/null 2>&1 &
        result=$?
        if [ "${result}" != "0" ]; then
            print-verbose "${XSERV}: ${result}"
            print-verbose "Possible Win-KeX server (SL) may not have been successful"
        fi
        status-kex-sl
    fi
    return 0
}

function stop-kex-sl() {
    print-verbose "Stopping Win-KeX server (SL)"
    # taskkill.exe /IM vcxsrv.exe /T /F >/dev/null 2>&1
    /init /mnt/c/Windows/system32/taskkill.exe taskkill.exe /IM vcxsrv.exe /T /F >/dev/null 2>&1
    if [ "$?" == "0" ]; then
        printf "\t${light_cyan}Win-KeX server (SL) stopped${reset}\n"
        return 0
    fi
    return 1
}

function status-kex-sl(){
    ##status=$(powershell.exe get-process vcxsrv 2>&1)
    # status=$(tasklist.exe | grep vcxsrv)
    status=$(/init /mnt/c/Windows/system32/taskkill.exe taskkill.exe | grep vcxsrv)
    if [ $? == "0" ]; then
        printf "\t${green}Win-KeX server (SL) is running${reset}\n"
        # 0 = true
        return 0
    else
        printf "\tWin-KeX server (SL) is stopped\n"
        # 1 = false
        return 1
    fi
}

function passwd-set-win() {
    print-verbose "Setting Win-KeX server (Win) password"
    print-verbose "*Do not need to set a read-only password*"
    vncpasswd
    return $?
}

function passwd-read-esm() {
    print-verbose "Getting password"
    local passwd
    stty_orig=$(stty -g) # save original terminal setting
    stty -echo           # turn-off echoing
    IFS= read -r passwd  # read the password
    stty "${stty_orig}"  # restore terminal setting
    echo "${passwd}"
}

function passwd-exist-esm() {
    print-verbose "Checking if password set for Win-KeX server (ESM)"
    USR=$(whoami)
    # cmdkey.exe /list:LegacyGeneric:target=TERMSRV/${HOST} | grep -q ${USR}
    /init /mnt/c/Windows/system32/cmdkey.exe cmdkey.exe /list:LegacyGeneric:target=TERMSRV/${HOST} | grep -q ${USR}
    return $?
}

function passwd-set-esm() {
    USR=$(whoami)
    printf "Please enter Win-KeX server (ESM) password for user ${USR}:"
    passwd=$(passwd-read-esm)
    printf "\n"
    # cmdkey.exe /generic:TERMSRV/${HOST} /user:${USR} /pass:${passwd} >/dev/null 2>&1 &
    /init /mnt/c/Windows/system32/cmdkey.exe cmdkey.exe /generic:TERMSRV/${HOST} /user:${USR} /pass:${passwd} >/dev/null 2>&1 &
}

function status-all() {
    status-kex-win
    status-kex-sl
    status-kex-esm
    wslg-socket-status
}

function status-kex-win() {
    if sessions-kex-win >/dev/null 2>&1; then
        printf "\t${green}Win-KeX server (Win) is running${reset}\n"
    else
        printf "\tWin-KeX server (Win) is stopped\n"
    fi
}

function sessions-kex-win() {
    local result
    # sessions=$(vncserver -list | sed s/"TigerVNC"/"Win-KeX"/)
    sessions=$(systemctl is-active vncserver@$SCREEN.service 2>&1)
    # if [[ ${sessions} == *"590"* ]]; then
    #     printf "\n${sessions}\n"
    #     printf "\nYou can use the Win-KeX client (Win) to connect to any of these displays\n"
    #     result=0
    if [[ ${sessions} == "active" ]]; then
        printf "\n$(echo "Port 590$SCREEN" | sed 's/://')\n"
        printf "\nYou can use the Win-KeX client (Win) to connect to any of these displays\n"
        result=0
    else
        if [ -n ${starting_kex} ]; then
            printf '\nError connecting to the Win-KeX server (Win)\n'
            printf 'Please try "'$0' start" to start the service\n'
            printf 'If the server fails to start, please try "'$0' kill" or restart your WSL 2 session and try again\n'
            result=1
        fi
    fi
    printf '\n\n'
    return ${result}
}

function start-client-win() {
    printf 'Starting Win-KeX client (Win)\n'
    if is-root; then
        SCREEN=":2"
        unset PASSWD
    else
        SCREEN=":1"
        # local PASSWD="-passwd ${HOME}/.config/tigervnc/passwd"
        local PASSWD="-passwd ${HOME}/.vnc/passwd"
    fi

    if [ -z ${MULTISCREEN} ]; then
        print-verbose "Skipping Multiscreen support"
        local FULLSCREEN="FullScreen=1"
    else
        print-verbose "Multiscreen support requested"
        local FULLSCREEN="FullScreen=0 FullScreenAllMonitors=0"
    fi

    # If Win-KeX is started from the Windows home directory, it fails to open the passwd file
    # Let's work around it by starting Win-KeX from the rootfs
    cd ~
    print-verbose "Running Win-KeX client (Win)"
    # ${VNCCLIENT} -SecurityTypes VeNCrypt,TLSVnc -ReconnectOnError ${RECONN_ON_ERR} ${PASSWD} ${FULLSCREEN} 127.0.0.1${SCREEN} >/dev/null 2>&1 &
    /init ${VNCCLIENT} ${VNCCLIENT} -SecurityTypes VeNCrypt,TLSVnc -ReconnectOnError ${RECONN_ON_ERR} ${PASSWD} ${FULLSCREEN} 127.0.0.1${SCREEN} >/dev/null 2>&1 &
    result=$?
    if [ "${result}" != "0" ]; then
        print-verbose "${VNCCLIENT}: ${result}"
        print-verbose "Possible Win-KeX client (Win) may not have been successful"
    fi
    cd - >/dev/null 2>&1
}

function start-client-esm() {
    printf 'Starting Win-KeX client (ESM)\n'
    if [ ! -f ~/.win-kex.rdp ]; then
        cp ${VERBOSE} ${WINKEXDIR}/xrdp/win-kex.rdp ~/.win-kex.rdp
    fi

    if ! passwd-exist-esm; then
        passwd-set-esm
    fi

    if [ -z ${SOUND} ]; then
        print-verbose "Skipping sound support"
        if [ -f ~/.config/autostart/pulseaudio.desktop ]; then
            rm -f ${VERBOSE} ~/.config/autostart/pulseaudio.desktop
        fi
    else
        print-verbose "Sound support requested"
        if [ ! -d ~/.config/autostart ]; then
            mkdir -p ${VERBOSE} ~/.config/autostart
        fi
        cp ${VERBOSE} ${WINKEXDIR}/xrdp/pulseaudio.desktop ~/.config/autostart/
    fi

    cd ~
    # mstsc.exe .win-kex.rdp /v:${HOST}:3390 &
    /init /mn/c/Windows/system32/mstsc.exe mstsc.exe .win-kex.rdp /v:${HOST}:3390 &
    result=$?
    if [ "${result}" != "0" ]; then
        print-verbose "mstsc.exe: ${result}"
        print-verbose "Possible Win-KeX client (ESM) may not have been successful"
    fi
    cd - >/dev/null 2>&1
    return $?
}

function start-client-wt() {
    printf 'Starting Win-KeX client (Windows Terminal)\n'
    while true; do
        clear
        printf "\n\t${blue}Win-KeX session is active\n\tClose this window to terminate Win-KeX${reset}\n"
        # If Win-KeX is started from the Windows home directory, it fails to open the passwd file
        # Let's work around it by starting Win-KeX from the rootfs
        cd ~
        if [ "${mode}" == "sl" ]; then
            start-client-sl
            while true; do
                read -n 1
            done
        elif [ "${mode}" == "esm" ]; then
            start-client-esm
            local pid=$!
            while kill -0 ${pid} 2>/dev/null; do
                sleep 1
            done
        else
            if [ -z ${MULTISCREEN} ]; then
                print-verbose "Skipping Multiscreen support"
                local FULLSCREEN="FullScreen=1"
            else
                print-verbose "Multiscreen support requested"
                local FULLSCREEN="FullScreen=0 FullScreenAllMonitors=0"
            fi
            # ${VNCCLIENT} -SecurityTypes VeNCrypt,TLSVnc -passwd ${HOME}/.config/tigervnc/passwd ${FULLSCREEN} 127.0.0.1:1
            ${VNCCLIENT} -SecurityTypes VeNCrypt,TLSVnc -passwd ${HOME}/.vnc/passwd ${FULLSCREEN} 127.0.0.1:1
        fi
        cd - >/dev/null 2>&1
        if ask "\n\tWin-KeX session disconnected\n\tWould you like to reconnect?" "Y"; then
            printf "\n\tReconnecting Win-KeX session\n"
        else
            stop-kex-win
            exit 0
        fi
    done
}

function run-xfdesktop() {
    print-verbose "Looking for: xfdesktop -Q"
    print-verbose "Waiting ${SLTIMEOUT} seconds"
    i=1
    nopid=0
    until pids=$(pidof xfdesktop); do
        xfdesktop -Q >/dev/null 2>&1
        i=$((i + 1))
        sleep 1
        if [ ${i} -ge ${SLTIMEOUT} ]; then
            nopid=1
            break
        fi
        if [ -n "${VERBOSE}" ]; then
            printf '.'
        fi
    done
    printf '\n'

    if [ ${nopid} == "1" ]; then
        printf "\t${light_cyan}Waited ${i} seconds for xfdesktop -Q (gave up)${reset}\n"
    fi

    return ${nopid}
}

function start-client-sl() {
    printf 'Starting Win-KeX client (SL)\n'
    # if [ "${USE_EXISTING_GUI_VARS}" != 1 ]; then
    #     sessions-kex-sl
    # fi
    sessions-kex-sl
    XFCE_DESKTOP_DISABLED="0"
    SESSION=${HOSTIP}:${XSERVSESSION}
    # if [ -z "$DISPLAY" ] || [ "${USE_EXISTING_GUI_VARS}" != 1 ]; then
    #     export DISPLAY=${SESSION}.0
    # fi
    export DISPLAY=${SESSION}.0
    export GDK_BACKEND=x11

    if [ "${NOWGL}" == "1" ]; then
        print-verbose "Skipping Windows OpenGL support"
    else
        print-verbose "Windows OpenGL support requested"
        export LIBGL_ALWAYS_INDIRECT=1
    fi

    if [ -z ${SOUND} ]; then
        print-verbose "Skipping sound support"
        unset PULSE_SERVER
    else
        print-verbose "Sound support requested"
        export PULSE_SERVER=tcp:${HOSTIP}
        # if [ -z "$PULSE_SERVER" ] || [ "${USE_EXISTING_GUI_VARS}" != 1 ]; then
        #     export PULSE_SERVER=tcp:${HOSTIP}
        # fi
    fi

    ## Clean up stale sessions first
    print-verbose "Killing session"
    # pkill -ef "dbus-launch --exit-with-session xfce4-session" >/dev/null 2>&1
    pkill -ef "exec xfce4-session" >/dev/null 2>&1

    ## Launch new Xfce session
    print-verbose "Starting session"
    # dbus-launch --exit-with-session xfce4-session >/dev/null 2>&1 &
    exec xfce4-session >/dev/null 2>&1 &

    SESSION_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/sessions/xfce4-session-"
    SESSION_FILE="${SESSION_CACHE}${SESSION}"
    print-verbose "Checking session: ${SESSION_FILE}"

    if [ -f ${SESSION_FILE} ]; then
        print-verbose "Found session file"
        if ! grep -q "xfdesktop" ${SESSION_FILE} >/dev/null 2>&1; then
            XFCE_DESKTOP_DISABLED="1"
            printf "\t${light_cyan}Win-KeX client (SL) is already enabled${reset}\n"
        fi
    fi

    if [ ! ${XFCE_DESKTOP_DISABLED} == "1" ]; then
        printf "\t${light_cyan}Enabling Win-KeX client (SL)${reset}\n"
        print-verbose "Waiting ${SLTIMEOUT} seconds for Win-KeX server (SL)"
        i=1
        nopid=0
        until pids=$(pidof xfdesktop); do
            i=$((i + 1))
            sleep 1
            if [ ${i} -ge ${SLTIMEOUT} ]; then
                nopid=1
                break
            fi
            if [ -n "${VERBOSE}" ]; then
                printf '.'
            fi
        done
        printf '\n'
        if [ ${nopid} == "0" ]; then
            printf "\t${light_cyan}xfDesktop started after ${i} seconds${reset}\n"
            printf "\t${light_cyan}Enabling transparency now${reset}\n"
            sleep 2
            run-xfdesktop
        else
            printf "\t${light_cyan}Waited ${i} seconds for xfDesktop (gave up)${reset}\n"
            printf "\tTry either:\n $0 --sl --wait [...]\n"
            printf "\t\t$0 --sl --wait [...]\n"
            printf "\t\tInstall vcxsrv on the host outside of WSL: https://www.docs.snigdhaos.org/wsl/win-kex-sl/\n"
            if [ -n "${VERBOSE}" ]; then
                printf '\n'
                cat "${log}"
            fi
            return 1
        fi
        ## Repeat, just in case
        if [ ${nopid} == "0" ]; then
            run-xfdesktop
        fi

        ## Save the session
        printf "\t${light_cyan}Saving Win-KeX server (SL) session${reset}\n"
        dbus-send --session --dest=org.xfce.SessionManager --print-reply /org/xfce/SessionManager org.xfce.Session.Manager.Checkpoint string:"" >/dev/null 2>&1
    fi

    printf "\t${light_cyan}Started Win-KeX server (SL)${reset}\n"
    return 0
}

function kill-kex() {
    print-verbose "Killing Win-KeX"
    stop-kex-win
    stop-kex-sl
    stop-kex-esm
    stop-sound
    wslg-socket-restore
    pkill ssh-agent
    pkill Xtigervnc
    pkill xiccd
    pkill pulseaudio
    pkill -9 -f pulseaudio.exe
    pkill xcape
    pkill Xorg
    pkill xrdp-chansrv
    return $?
}

function start-sound() {
    print-verbose "Starting sound"
    cd /usr/lib/win-kex/pulse
    # ./pulseaudio.exe -F config.pa >/dev/null 2>&1 &
    /init ./pulseaudio.exe pulseaudio.exe -F config.pa >/dev/null 2>&1 &
    cd - >/dev/null 2>&1
}

function stop-sound() {
    print-verbose "Stopping sound"
    pkill -9 -f pulseaudio.exe
}
# Deleting wayland is necessary
rm -rf /run/user/1000/wayland-0*
unset mode
unset cmd
while [[ $# -gt 0 ]]; do
    case $1 in
        # PARAMETERS:
        -i|--ip)
            # Use IP address instead of localhost
            # Fixes latency issues on ARM (as with version 19041.423)
            IP=1
            shift
            ;;
        -s|--sound)
            SOUND=1
            shift
            ;;
        -m|--multiscreen)
            MULTISCREEN=1
            XMULTIMONITORS="-nomultimonitors"
            shift
            ;;
        -n|--nowgl)
            NOWGL=1
            shift
            ;;
        -r|--norc)
            RECONN_ON_ERR=0
            shift
            ;;
        -w|--wait)
            # Wait longer for desktop to start in SL mode when launched for first time
            # Can be used on slower machines where the desktop takes longer than
            # 100 seconds to start. Only required on first start to enable transparency
            SLTIMEOUT=300
            shift
            ;;
        # --use-existing-gui-vars)
        #     USE_EXISTING_GUI_VARS=1
        #     shift
            ;;
        # MODES:
        esm|--esm)
            mode=esm
            shift
            ;;
        sl|--sl)
            mode=sl
            shift
            ;;
        win|--win)
            mode=win
            shift
            ;;
        # COMMANDS:
        wslg-remove|--wslg-remove)
            cmd=remove_wslg
            shift
            ;;
        wslg-restore|--wslg-restore)
            cmd=restore_wslg
            shift
            ;;
        wslg-status|--wslg-status)
            cmd=status_wslg
            shift
            ;;
        kill|--kill)
            cmd=kill
            shift
            ;;
        passwd|--passwd)
            cmd=passwd
            shift
            ;;
        start|--start)
            cmd=start
            shift
            ;;
        start-client|start-c|--start-client|--start-c)
            cmd=start-client
            shift
            ;;
        start-sound|--start-sound)
            cmd=start-sound
            shift
            ;;
        status|--status)
            cmd=status
            shift
            ;;
        stop|--stop)
            cmd=stop
            shift
            ;;
        stop-sound|--stop-sound)
            cmd=stop-sound
            shift
            ;;
        wtstart|--wtstart)
            cmd=wtstart
            shift
            ;;
        help|-h|--help)
            cmd=help
            shift
            ;;
        --version)
            cmd=version
            shift
            ;;
        --verbose)
            VERBOSE=-v
            shift
            ;;
        *)
            printf "Unknown option: $1\n"
            if [ -z ${cmd} ]; then
                cmd=default
            fi
            shift
            ;;
    esac
done

if [ "${SOUND}" == "1" ] && [ ! "${mode}"  == "esm" ] && [ ! "${ARCH}" == "aarch64" ]; then
    stop-sound
    start-sound
fi

if [ "${IP}" == "1" ]; then
    HOST=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
    print-verbose "IP: ${HOST}"
fi

case ${cmd} in
    remove_wslg)
        if wslg-socket-check; then
            wslg-socket-remove
        fi
        exit
        ;;
    restore_wslg)
        if ! wslg-socket-check; then
            wslg-socket-restore
        fi
        exit
        ;;
    status_wslg)
        wslg-socket-status
        exit
        ;;
esac

if [ "${ARCH}" == "aarch64" ]; then
    case ${cmd} in
        start)
            if [ "${mode}"  == "sl" ]; then
                print-wrong-arch
            elif [ "${mode}"  == "esm" ]; then
                start-kex-esm
            else
                start-kex-esm
            fi
            ;;
        stop)
            if [ "${mode}"  == "sl" ]; then
                print-wrong-arch
            elif [ "${mode}"  == "esm" ]; then
                stop-kex-esm
            else
                stop-kex-esm
            fi
            ;;
        start-client)
            if [ "${mode}"  == "sl" ]; then
                print-wrong-arch
            elif [ "${mode}"  == "esm" ]; then
                start-client-esm
            else
                start-client-esm
            fi
            ;;
        status)
            if [ "${mode}"  == "sl" ]; then
                status-kex-sl
            elif [ "${mode}"  == "esm" ]; then
                status-kex-esm
            elif [ "${mode}"  == "win" ]; then
                status-kex-win
            else
                status-all
            fi
            ;;
        passwd)
            if [ "${mode}" == "esm" ]; then
                passwd-set-esm
            elif [ ! "${mode}"  == "sl" ]; then
                passwd-set-esm
            else
                printf "\n\t${red}This command is not supported in \"${mode}\" mode${reset}\n"
            fi
            ;;
        kill)
            kill-kex
            ;;
        start-sound)
            print-wrong-arch
            ;;
        stop-sound)
            print-wrong-arch
            ;;
        wtstart)
            if [ "${mode}"  == "sl" ]; then
                print-wrong-arch
            elif [ "${mode}"  == "esm" ]; then
                stop-kex-esm
                start-kex-esm
                start-client-wt
            else
                mode=esm
                stop-kex-esm
                start-kex-esm
                start-client-wt
            fi
            ;;
        help)
            print-help
            ;;
        version)
            print-version
            ;;
        *)
            if [ "${mode}"  == "sl" ]; then
                print-wrong-arch
            elif [ "${mode}"  == "win" ]; then
                print-wrong-arch
            else
                start-kex-esm
                start-client-esm
            fi
            ;;
    esac
else
    case ${cmd} in
        start)
            if [ "${mode}"  == "sl" ]; then
                start-kex-sl
            elif [ "${mode}"  == "esm" ]; then
                start-kex-esm
            else
                start-kex-win
            fi
            ;;
        stop)
            if [ "${mode}"  == "sl" ]; then
                stop-kex-sl
            elif [ "${mode}"  == "esm" ]; then
                stop-kex-esm
            else
                stop-kex-win
            fi
            ;;
        start-client)
            if [ "${mode}"  == "sl" ]; then
                start-client-sl
            elif [ "${mode}"  == "esm" ]; then
                start-client-esm
            else
                start-client-win
            fi
            ;;
        status)
            if [ "${mode}"  == "sl" ]; then
                status-kex-sl
            elif [ "${mode}"  == "esm" ]; then
                status-kex-esm
            elif [ "${mode}"  == "win" ]; then
                status-kex-win
            else
                status-all
            fi
            ;;
        passwd)
            if [ "${mode}" == "esm" ]; then
                passwd-set-esm
            elif [ ! "${mode}"  == "sl" ]; then
                passwd-set-win
            else
                printf "\n\t${red}This command is not supported in \"${mode}\" mode${reset}\n"
            fi
            ;;
        kill)
            kill-kex
            ;;
        start-sound)
            stop-sound
            start-sound
            ;;
        stop-sound)
            stop-sound
            ;;
        wtstart)
            if [ "${mode}"  == "sl" ]; then
                start-kex-sl
                start-client-wt
            elif [ "${mode}"  == "esm" ]; then
                stop-kex-esm
                start-kex-esm
                start-client-wt
            else
                start-kex-win
                start-client-wt
            fi
            ;;
        help)
            print-help
            ;;
        version)
            print-version
            ;;
        *)
            if [ "${mode}"  == "sl" ]; then
                start-kex-sl
                start-client-sl
            elif [ "${mode}"  == "esm" ]; then
                start-kex-esm
                start-client-esm
            else
                start-kex-win
                start-client-win
            fi
            ;;
    esac
fi
