#!/bin/bash

function showHelp() {
	echo "mtm-ssh-vpn [args] command cmd_args"
	echo ""
	echo "args :"
	echo "  --help    Show help"
	echo "command :"
	echo "  status"
	echo "  connect profile"
	echo "  disconnect profile"
	echo "  disconnect-all"
	echo "cmd_args :"
	echo "  profile   Name of the profile (~/.config/mtm-ssh-proxy/*)"
}

if [ "${1}" == "" ]; then
	showHelp
	exit 1
fi
case ${1} in
	"--help")
		showHelp
		exit 0
	;;
	"status" | "disconnect-all");;
	"connect" | "disconnect")
		if [ "${2}" == "" ] || [[ "${2}" == */* ]]; then
			showHelp
			exit 1
		fi
	;;
	*)
		showHelp
		exit 1
	;;
esac

declare -r CONFIG_DIR=~/.config/mtm-ssh-proxy
declare -r TMP_DIR=/tmp/mtm-ssh-proxy-"${USER}/vpn"

read_config() {
	declare -r FILE=${1}
	declare -r KEYNAME=${2}
	declare -r DEFAULT=${3}
	if [ -f "${FILE}" ]; then
		if grep -v "#" "${FILE}" | grep -q "${KEYNAME}="; then
			VALUE=$(grep -v "#" "${FILE}" | grep "^${KEYNAME}=" | sed 's/'"${KEYNAME}"'=//')
			echo "${VALUE}"
			return 0
		fi
	fi
	echo "${DEFAULT}"
}

status() {
	if [ -d "${TMP_DIR}" ] && [ "$(find "${TMP_DIR}" -maxdepth 0 -empty -exec echo 1 \;)" == "" ]; then
		for FILE in "${TMP_DIR}"/*; do
			PROFILE=$(basename "${FILE}")
			PROXY=$(grep 'PROXY=' "${FILE}" | sed 's/PROXY=//')
			echo -e "${PROFILE}\t${PROXY}"
		done
	else
		echo "No vpn open"
	fi
}

connect() {
	declare -r CONFIG=${CONFIG_DIR}/config
	declare -r FILE=${CONFIG_DIR}/profiles/${1}
	if [ ! -f "${FILE}" ]; then
		echo "Error: Profile not found" >&2
		exit 1
	fi
	declare -r PROFILE=${1}
	if [ -f "${TMP_DIR}/${PROFILE}" ]; then
		echo "Error: VPN already start" >&2
		exit 1
	fi
	declare PROXY=""
	declare SUBNETS="0.0.0.0/0"
	declare EXCLUDE_SUBNETS=""
	declare REDIRECT_DNS=1
	SUBNETS=$(read_config "${CONFIG}" "SUBNETS" "${SUBNETS}")
	EXCLUDE_SUBNETS=$(read_config "${CONFIG}" "EXCLUDE_SUBNETS" "${EXCLUDE_SUBNETS}")
	REDIRECT_DNS=$(read_config "${CONFIG}" "REDIRECT_DNS" "${REDIRECT_DNS}")
	PROXY=$(read_config "${FILE}" "PROXY" "${PROXY}")
	SUBNETS=$(read_config "${FILE}" "SUBNETS" "${SUBNETS}")
	EXCLUDE_SUBNETS=$(read_config "${FILE}" "EXCLUDE_SUBNETS" "${EXCLUDE_SUBNETS}")
	REDIRECT_DNS=$(read_config "${FILE}" "REDIRECT_DNS" "${REDIRECT_DNS}")
	echo "Connecting to ${PROFILE}"
	echo "PROXY           : ${PROXY}"
	echo "SUBNETS         : ${SUBNETS}"
	echo "EXCLUDE_SUBNETS : ${EXCLUDE_SUBNETS}"
	echo "REDIRECT_DNS    : ${REDIRECT_DNS}"
	declare -r PIDFILE=$(mktemp -u)
	CMD="sshuttle --user ${USER} -D --pidfile ${PIDFILE} -r ${PROXY}"
	if [ "${REDIRECT_DNS}" == 1 ]; then
		CMD+=" --dns"
	fi
	# shellcheck disable=SC2206
	EXCLUDE_SUBNETS=(${EXCLUDE_SUBNETS})
	for EXCLUDE_SUBNET in "${EXCLUDE_SUBNETS[@]}"; do
		CMD+=" -x ${EXCLUDE_SUBNET}"
	done
	# shellcheck disable=SC2206
	SUBNETS=(${SUBNETS})
	for SUBNET in "${SUBNETS[@]}"; do
		CMD+=" ${SUBNET}"
	done
	if [ ! -d "${TMP_DIR}" ]; then
		mkdir -p "${TMP_DIR}"
	fi
	eval "${CMD}"
	{
		echo "PROXY=${PROXY}"
		echo "SUBNETS=${SUBNETS[*]}"
		echo "EXCLUDE_SUBNETS=${EXCLUDE_SUBNETS[*]}"
		echo "REDIRECT_DNS=${REDIRECT_DNS}"
		echo "PID=$(cat "${PIDFILE}")"
	} > "${TMP_DIR}/${PROFILE}"
}

disconnect() {
	declare ERROR=0
	if [ -d "${TMP_DIR}" ] && [ "$(find "${TMP_DIR}" -maxdepth 0 -empty -exec echo 1 \;)" == "" ]; then
		declare -r FILE=${TMP_DIR}/${1}
		declare -r PROFILE=$(basename "${FILE}")
		declare -r PID=$(grep 'PID=' "${FILE}" | sed 's/PID=//')
		if ! kill "${PID}"; then
			echo "Error: disconnecting vpn ${PROFILE}" >&2
			ERROR=1
		fi
		rm "${TMP_DIR}/${PROFILE}"
	fi
	return "${ERROR}"
}

disconnect_all() {
	declare ERROR=0
	if [ -d "${TMP_DIR}" ] && [ "$(find "${TMP_DIR}" -maxdepth 0 -empty -exec echo 1 \;)" == "" ]; then
		for FILE in "${TMP_DIR}"/*; do
			declare -r PROFILE=$(basename "${FILE}")
			if [ "$(disconnect "${PROFILE}")" == "1" ]; then
				ERROR=1
			fi
		done
	fi
	return "${ERROR}"
}

case ${1} in
	"status") status;;
	"connect") connect "${2}";;
	"disconnect")
		if [ "$(disconnect "${2}")" == "1" ]; then
			exit 1
		fi
	;;
	"disconnect-all")
		if [ "$(disconnect_all)" == "1" ]; then
			exit 1
		fi
	;;
	*)
		showHelp
		exit 1
	;;
esac
