#!/usr/bin/env zsh

# initialize variables
DAEMON=bitcoin
NETWORK=mainnet
FEATURES=default
DB_FOLDER=/electrs
NODENAME=$(hostname|cut -d . -f1)
LOCATION=$(hostname|cut -d . -f2)
USAGE="Usage: $0 (mainnet|testnet|signet|liquid|liquidtestnet) [popular-scripts]"

# load rust if necessary
if [ -e "${HOME}/.cargo/env" ];then
	source "${HOME}/.cargo/env"
	export PATH="${HOME}/.cargo/bin:${PATH}"
fi

# which OS?
case "$(uname -s)" in
	FreeBSD)
		OS=FreeBSD
		NPROC=$(sysctl -n hw.ncpu)
		export CC=/usr/local/bin/clang17
		export CXX=/usr/local/bin/clang++17
		export CPP=/usr/local/bin/clang-cpp17
		export RUSTFLAGS="-C linker=clang17"
	;;
	Darwin)
		OS=Darwin
		NPROC=$(sysctl -n hw.ncpu)
	;;
	Linux)
		OS=Linux
		NPROC=$(grep -c proc /proc/cpuinfo)
	;;
	*)
		OS=Unknown
		NPROC=4
	;;
esac

# which network?
case "${1}" in
	mainnet)
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="20 4 * * *"
	;;
	testnet)
		NETWORK=testnet
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="2 4 * * *"
	;;
	testnet4)
		NETWORK=testnet4
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="17 4 * * *"
	;;
	signet)
		NETWORK=signet
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="9 4 * * *"
	;;
	liquid)
		DAEMON=elements
		NETWORK=liquid
		FEATURES=liquid
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="12 4 * * *"
	;;
	liquidtestnet)
		DAEMON=elements
		NETWORK=liquidtestnet
		FEATURES=liquid
		THREADS=$((NPROC / 8))
		CRONJOB_TIMING="17 4 * * *"
	;;
	*)
		echo "${USAGE}"
		exit 1
	;;
esac

# Run the popular address txt file generator before each run
POPULAR_SCRIPTS_FOLDER="${HOME}/popular-scripts/${NETWORK}"
POPULAR_SCRIPTS_FILE_RAW="${POPULAR_SCRIPTS_FOLDER}/popular-scripts-raw.txt"
POPULAR_SCRIPTS_FILE="${POPULAR_SCRIPTS_FOLDER}/popular-scripts.txt"

# This function runs the job for generating the popular scripts text file for the precache arg
generate_popular_scripts() {
	mkdir -p "${POPULAR_SCRIPTS_FOLDER}"

	## Use nproc * 4 threads to generate the txt file (lots of iowait, so 2x~4x core count is ok)
	## Only pick up addresses with 101 history events or more
	## (Without lowering MIN_HISTORY_ITEMS_TO_CACHE this is the lowest we can go)
	## It prints out progress to STDERR
	echo "[*] Generating popular-scripts using ${THREADS} threads..."
	cd "${HOME}/electrs"
	HIGH_USAGE_THRESHOLD=101 \
	JOB_THREAD_COUNT=${THREADS} \
	nice cargo run \
		--release \
		--bin popular-scripts \
		--features "${FEATURES}" \
		-- \
		--network "${NETWORK}" \
		--db-dir "${DB_FOLDER}" \
		> "${POPULAR_SCRIPTS_FILE_RAW}"

	## Only overwrite the existing file if the popular-scripts cargo run succeeded
	if [ "$?" = "0" ];then
		## Sorted and deduplicated just in case
		echo "Sorting popular scripts for final results..."
		sort "${POPULAR_SCRIPTS_FILE_RAW}" | uniq > "${POPULAR_SCRIPTS_FILE}"
	fi

	rm "${POPULAR_SCRIPTS_FILE_RAW}"
}

# This function is for inserting the cronjob for generating the popular scripts
CRONJOB_CMD="\"${HOME}/electrs/start\" \"${NETWORK}\" popular-scripts"
echo "${CRONJOB_TIMING} ${CRONJOB_CMD}"

case "${2}" in
	popular-scripts)
		echo "[*] Only generate popular-scripts, then exit"
		generate_popular_scripts
		exit 0
	;;
	version)
		echo "[*] Only print versions, then exit"
		cargo run --bin electrs --release -- --version
		cargo run --bin popular-scripts --release -- --version
		exit 0
	;;
	"")
		# If the 2nd arg isn't passed, just run the normal electrs script as-is
	;;
	*)
		echo "${USAGE}"
		exit 1
	;;
esac

# run in loop in case of crash
until false
do
	# reset CWD
	cd "${HOME}/electrs"

	# disable making electrs.core files
	ulimit -c 0

	# prepare run-time variables
	UTXOS_LIMIT=500
	ELECTRUM_TXS_LIMIT=500
	MAIN_LOOP_DELAY=500
	DAEMON_CONF="${HOME}/${DAEMON}.conf"
	HTTP_SOCKET_FILE="${HOME}/socket/esplora-${DAEMON}-${NETWORK}"
	RPC_SOCKET_FILE="${HOME}/socket/electrum-${DAEMON}-${NETWORK}"

	# get RPC credentials from bitcoin.conf or elements.conf directly
	echo "[*] Getting RPC credentials from ${DAEMON_CONF}"
	RPC_USER=$(grep 'rpcuser=' "${DAEMON_CONF}"|cut -d = -f2|head -1)
	RPC_PASS=$(grep 'rpcpassword=' "${DAEMON_CONF}"|cut -d = -f2|head -1)

	# override limits based on hostname
	if [ "${NODENAME}" = "node201" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
		MAIN_LOOP_DELAY=14000
	fi
	if [ "${NODENAME}" = "node204" ] && [ "${LOCATION}" = "sg1" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node204" ] && [ "${LOCATION}" = "hnl" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node206" ] && [ "${LOCATION}" = "tk7" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node211" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node212" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node213" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NODENAME}" = "node214" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${NETWORK}" = "testnet4" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi
	if [ "${LOCATION}" = "fmt" ];then
		UTXOS_LIMIT=9000
		ELECTRUM_TXS_LIMIT=9000
	fi

	if [ ! -e "${POPULAR_SCRIPTS_FILE}" ];then
		generate_popular_scripts
	fi

	# Run the electrs process (Note: db-dir is used in both commands)
	nice cargo run \
		--release \
		--bin electrs \
		--features "${FEATURES}" \
		-- \
		--network "${NETWORK}" \
		--daemon-dir "${HOME}" \
		--db-dir "${DB_FOLDER}" \
		--main-loop-delay "${MAIN_LOOP_DELAY}" \
		--rpc-socket-file "${RPC_SOCKET_FILE}" \
		--http-socket-file "${HTTP_SOCKET_FILE}" \
		--precache-scripts "${POPULAR_SCRIPTS_FILE}" \
		--precache-threads "${THREADS}" \
		--cookie "${RPC_USER}:${RPC_PASS}" \
		--cors '*' \
		--address-search \
		--utxos-limit "${UTXOS_LIMIT}" \
		--electrum-txs-limit "${ELECTRUM_TXS_LIMIT}" \
		-vv
	sleep 1
done
