#!/usr/bin/env bash

set -xeuo pipefail

SCRIPT_NAME=$(basename "$0")

function usage()
{
    cat <<EOF
${SCRIPT_NAME}: Launch a chutney network to test arti

Usage:
  ${SCRIPT_NAME} [modules] : Launch chutney, and the provided modules.

Options:
  -h: Print this message.
  -n <network>: Name of the chutney network to launch (default: basic)

Modules:
  "proxy": Launch a arti-based SOCKS proxy.
EOF
}

PROXY=no
NETWORK="basic"
while getopts "hn:" opt ; do
    case "$opt" in
	h) usage
	   exit 0
	   ;;
	n) NETWORK="$OPTARG"
	   ;;
	*) echo "Unknown option. (Run $0 -h for usage)"
	   exit 1
	   ;;
    esac
done

# Remove the parsed flags
shift $((OPTIND-1))

for module in "$@"; do
    case "$module" in
	proxy) PROXY=yes
	       ;;
	*) echo "Unrecognized module. (Run $0 -h for usage)"
	   ;;
    esac
done

target="networks/$NETWORK"
cd "$(git rev-parse --show-toplevel)"
echo "target=$target" > tests/chutney/arti.run

if [ -z "${CHUTNEY_PATH:-}" ]; then
    # CHUTNEY_PATH isn't set; try cloning or updating a local chutney.
    if [ -d chutney ]; then
	(cd ./chutney && git pull)
    else
	git clone https://gitlab.torproject.org/tpo/core/chutney
    fi
    CHUTNEY_PATH="$(pwd)/chutney"
    export CHUTNEY_PATH
else
    # CHUTNEY_PATH is set; tell the user so.
    echo "CHUTNEY_PATH is ${CHUTNEY_PATH}; using your local copy of chutney."
fi

if [ ! -e "${CHUTNEY_PATH}/${target}" ]; then
    echo "Target network description ${CHUTNEY_PATH}/${target} not found."
    exit 1
fi

"${CHUTNEY_PATH}/chutney" configure "${CHUTNEY_PATH}/$target"
"${CHUTNEY_PATH}/chutney" start "${CHUTNEY_PATH}/$target"
CHUTNEY_START_TIME=180 "${CHUTNEY_PATH}"/chutney wait_for_bootstrap "${CHUTNEY_PATH}/$target"
"${CHUTNEY_PATH}"/chutney verify "${CHUTNEY_PATH}/$target"

if [ "$PROXY" = "no" ] ; then
    exit 0
fi

ARTI_FLAGS=()
if [ "$(id -u)" = "0" ] ; then
    # If we are root, then we're probably running from CI.  Tell Arti
    # that's okay.
    ARTI_FLAGS+=("-o" "application.allow_running_as_root=true")
fi

if [ -x ./target/x86_64-unknown-linux-gnu/debug/arti ]; then
	cmd=./target/x86_64-unknown-linux-gnu/debug/arti
else
	cargo build
	cmd=./target/debug/arti
fi

(
	set +e
	"$cmd" proxy -c "${CHUTNEY_PATH}/net/nodes/arti.toml" -d 35353 \
	       "${ARTI_FLAGS[@]}" &
	arti_pid=$!
	echo "pid=$arti_pid" >> tests/chutney/arti.run
	wait "$arti_pid"
	echo "result=$?" >> tests/chutney/arti.run
) & disown

# Wait for arti to start listening (it does so "immediately", but we don't want to get there first)
# Really there should be a proper daemon startup protocol here, but arti doesn't have one yet.
for idx in $(seq 30); do
    if : >&/dev/null </dev/tcp/127.0.0.1/9150 ; then
	echo "Port 9150 seems open."
	break
    elif [ "$idx" == 30 ]; then
	echo "Waited 30 seconds without result; giving up on port 9150."
	exit 1
    else
	echo "waiting for port 9150..."
	sleep 1
    fi
    # verify Arti did not fail early
    # shellcheck disable=SC1091
    source tests/chutney/arti.run
    pid="${pid:?}"
    if ! kill -0 "$pid"; then
	result="${result:?}"
        echo "Arti failed to start with code $result"
	exit 1
    fi
done
