#!/usr/bin/env bash
set -euo pipefail

##########################################################
################## Check dependencies ####################
##########################################################

check_dependencies () {
  for cmd in "$@"; do
    if ! command -v $cmd >/dev/null 2>&1; then
      echo "This script requires \"${cmd}\" to be installed"
      exit 1
    fi
  done
}

if [ ! "$(uname -s)" == "Linux" ]; then
  echo "Sorry, Umbrel only supports Linux-based systems at this point."
  echo
  echo "You may work around this by modifying the configuration script yourself, but it's highly experimental."
  echo "If you get it working, we hope you consider making a PR. :)"
  exit 1
fi

check_dependencies docker docker-compose dirname readlink

# Switch to Umbrel's root directory
UMBREL_ROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")"/..)"
if [[ ! -d "$UMBREL_ROOT" ]]; then
  echo "Root dir does not exist '$UMBREL_ROOT'"
  exit 1
fi
cd "$UMBREL_ROOT"

# Make sure we use the status dir from the real Umbrel installation if this is
# an OTA update.
STATUS_DIR="${UMBREL_ROOT}/statuses"
if [[ -f "${UMBREL_ROOT}/../.umbrel" ]]; then
  STATUS_DIR="${UMBREL_ROOT}/../statuses"
fi

# Configure for mainnet or testnet or regtest depending
# upon the user-supplied value of $NETWORK
BITCOIN_NETWORK="${NETWORK:-mainnet}"

if [ "$BITCOIN_NETWORK" != "mainnet" ] && [ "$BITCOIN_NETWORK" != "testnet" ] && [ "$BITCOIN_NETWORK" != "regtest" ]; then
  echo "Error: Umbrel can only be configured for mainnet (default), testnet or regtest"
  exit 1
fi

echo
echo "======================================"
if [[ -f "${STATUS_DIR}/configured" ]]; then
  echo "=========== RECONFIGURING ============"
else
  echo "============ CONFIGURING ============="
fi
echo "=============== UMBREL ==============="
echo "======================================"
echo


##########################################################
############### Setup configuration files ###############
##########################################################

# Store paths to intermediary config files
NGINX_CONF_FILE="./templates/nginx.conf"
TOR_PROXY_CONF_FILE="./templates/torrc-proxy"
TOR_SERVER_CONF_FILE="./templates/torrc-server"
ENV_FILE="./templates/.env"

# Remove intermediary files if they exist from any
# previous unclean configuration run
[[ -f "$NGINX_CONF_FILE" ]] && rm -f "$NGINX_CONF_FILE"
[[ -f "$TOR_PROXY_CONF_FILE" ]] && rm -f "$TOR_PROXY_CONF_FILE"
[[ -f "$TOR_SERVER_CONF_FILE" ]] && rm -f "$TOR_SERVER_CONF_FILE"
[[ -f "$ENV_FILE" ]] && rm -f "$ENV_FILE"

# Copy template configs to intermediary configs
[[ -f "./templates/nginx-sample.conf" ]] && cp "./templates/nginx-sample.conf" "$NGINX_CONF_FILE"
[[ -f "./templates/torrc-proxy-sample" ]] && cp "./templates/torrc-proxy-sample" "$TOR_PROXY_CONF_FILE"
[[ -f "./templates/torrc-server-sample" ]] && cp "./templates/torrc-server-sample" "$TOR_SERVER_CONF_FILE"
[[ -f "./templates/.env-sample" ]] && cp "./templates/.env-sample" "$ENV_FILE"


##########################################################
############ Generate configuration variables ############
##########################################################

# Load existing credentials if we have some
[[ -f "./.env" ]] && source "./.env"
[[ ! -z ${PREV_ENV_FILE+x} ]] && [[ -f "${PREV_ENV_FILE}" ]] && source "${PREV_ENV_FILE}"

# Define Umbrel Networking
NETWORK_IP="10.21.0.0"
GATEWAY_IP="10.21.0.1"
NGINX_IP="10.21.21.2"
NGINX_PORT="${NGINX_PORT:-80}"
DASHBOARD_IP="10.21.21.3"
MANAGER_IP="10.21.21.4"
AUTH_IP="10.21.21.6"
AUTH_PORT="2000"
TOR_PROXY_IP="10.21.21.11"
TOR_PROXY_PORT="9050"

# App specific state
BITCOIN_IP="10.21.21.8"
BITCOIN_RPC_PORT="8332"
BITCOIN_P2P_PORT="8333"
BITCOIN_ZMQ_RAWBLOCK_PORT="28332"
BITCOIN_ZMQ_RAWTX_PORT="28333"
BITCOIN_ZMQ_HASHBLOCK_PORT="28334"
BITCOIN_ZMQ_SEQUENCE_PORT="28335"
LND_IP="10.21.21.9"
LND_GRPC_PORT="10009"
LND_REST_PORT="8080"
ELECTRUM_IP="10.21.21.10"
ELECTRUM_PORT="50001"

if [[ -z ${UMBREL_AUTH_SECRET+x} ]]; then
  UMBREL_AUTH_SECRET="$(openssl rand -hex 32)"
fi

# Generate RPC credentials
if [[ -z ${BITCOIN_RPC_USER+x} ]] || [[ -z ${BITCOIN_RPC_PASS+x} ]] || [[ -z ${BITCOIN_RPC_AUTH+x} ]]; then
  echo "Generating auth credentials"
  echo
  BITCOIN_RPC_USER="umbrel"
  BITCOIN_RPC_DETAILS=$("./scripts/rpcauth.py" "$BITCOIN_RPC_USER")
  BITCOIN_RPC_PASS=$(echo "$BITCOIN_RPC_DETAILS" | tail -1)
  BITCOIN_RPC_AUTH=$(echo "$BITCOIN_RPC_DETAILS" | head -2 | tail -1 | sed -e "s/^rpcauth=//")
fi

# Pull Tor image and generate Tor password
if [[ -z ${TOR_PASSWORD+x} ]] || [[ -z ${TOR_HASHED_PASSWORD+x} ]]; then
  echo "Generating Tor password"
  echo
  TOR_PASSWORD=$("./scripts/rpcauth.py" "itdoesntmatter" | tail -1)
  TOR_HASHED_PASSWORD=$(docker run --rm getumbrel/tor:0.4.7.8@sha256:2ace83f22501f58857fa9b403009f595137fa2e7986c4fda79d82a8119072b6a --quiet --hash-password "$TOR_PASSWORD")
fi

##########################################################
### Update config files with configuration variables #####
##########################################################

# Update RPC, P2P and ZMQ Ports
sed -i "s/BITCOIN_RPC_PORT=<port>/BITCOIN_RPC_PORT=$BITCOIN_RPC_PORT/g;" "$ENV_FILE"
sed -i "s/BITCOIN_P2P_PORT=<port>/BITCOIN_P2P_PORT=$BITCOIN_P2P_PORT/g;" "$ENV_FILE"

# Add rpcauth
sed -i "s/BITCOIN_RPC_AUTH=<rpcauth>/BITCOIN_RPC_AUTH='$BITCOIN_RPC_AUTH'/g;" "$ENV_FILE"

# Add RPC credentials to env file
sed -i "s/BITCOIN_RPC_USER=<username>/BITCOIN_RPC_USER=$BITCOIN_RPC_USER/g;" "$ENV_FILE"
sed -i "s/BITCOIN_RPC_PASS=<password>/BITCOIN_RPC_PASS=$BITCOIN_RPC_PASS/g;" "$ENV_FILE"

# Add chain to env file
sed -i "s/BITCOIN_NETWORK=<network>/BITCOIN_NETWORK=$BITCOIN_NETWORK/g;" "$ENV_FILE"

# Add Tor password
sed -i "s/HashedControlPassword <password>/HashedControlPassword $TOR_HASHED_PASSWORD/g;" "$TOR_PROXY_CONF_FILE"
sed -i "s/TOR_PASSWORD=<password>/TOR_PASSWORD=$TOR_PASSWORD/g;" "$ENV_FILE"
sed -i "s/TOR_HASHED_PASSWORD=<password>/TOR_HASHED_PASSWORD=$TOR_HASHED_PASSWORD/g;" "$ENV_FILE"

# Store docker binary path
DOCKER_BINARY=$(readlink -f "$(which docker)")
sed -i "s#DOCKER_BINARY=<path>#DOCKER_BINARY=$DOCKER_BINARY#g;" "$ENV_FILE"

# TODO: Update all the above code to use this simpler logic
for template in "${NGINX_CONF_FILE}" "${TOR_PROXY_CONF_FILE}" "${TOR_SERVER_CONF_FILE}" "${ENV_FILE}"; do
  # Umbrel
  sed -i "s/<network-ip>/${NETWORK_IP}/g" "${template}"
  sed -i "s/<gateway-ip>/${GATEWAY_IP}/g" "${template}"
  sed -i "s/<nginx-ip>/${NGINX_IP}/g" "${template}"
  sed -i "s/<nginx-port>/${NGINX_PORT}/g" "${template}"
  sed -i "s/<dashboard-ip>/${DASHBOARD_IP}/g" "${template}"
  sed -i "s/<manager-ip>/${MANAGER_IP}/g" "${template}"
  sed -i "s/<auth-ip>/${AUTH_IP}/g" "${template}"
  sed -i "s/<auth-port>/${AUTH_PORT}/g" "${template}"
  sed -i "s/<umbrel-auth-secret>/${UMBREL_AUTH_SECRET}/g" "${template}"

  # App specific state  
  sed -i "s/<bitcoin-ip>/${BITCOIN_IP}/g" "${template}"
  sed -i "s/<bitcoin-p2p-port>/${BITCOIN_P2P_PORT}/g" "${template}"
  sed -i "s/<bitcoin-rpc-port>/$BITCOIN_RPC_PORT/g" "${template}"
  sed -i "s/<lnd-ip>/${LND_IP}/g" "${template}"
  sed -i "s/<lnd-grpc-port>/${LND_GRPC_PORT}/g" "${template}"
  sed -i "s/<lnd-rest-port>/${LND_REST_PORT}/g" "${template}"
  sed -i "s/<electrum-ip>/${ELECTRUM_IP}/g" "${template}"
  sed -i "s/<electrum-port>/${ELECTRUM_PORT}/g" "${template}"
  sed -i "s/<tor-proxy-ip>/${TOR_PROXY_IP}/g" "${template}"
  sed -i "s/<tor-proxy-port>/${TOR_PROXY_PORT}/g" "${template}"
  sed -i "s/<zmq-rawblock-port>/${BITCOIN_ZMQ_RAWBLOCK_PORT}/g;" "${template}"
  sed -i "s/<zmq-rawtx-port>/${BITCOIN_ZMQ_RAWTX_PORT}/g;" "${template}"
  sed -i "s/<zmq-hashblock-port>/${BITCOIN_ZMQ_HASHBLOCK_PORT}/g;" "${template}"
  sed -i "s/<zmq-sequence-port>/${BITCOIN_ZMQ_SEQUENCE_PORT}/g;" "${template}"
done

##########################################################
############## Override main config files ################
##########################################################

mv -f "$NGINX_CONF_FILE" "./nginx/nginx.conf"
mv -f "$TOR_PROXY_CONF_FILE" "./tor/torrc-proxy"
mv -f "$TOR_SERVER_CONF_FILE" "./tor/torrc-server"
mv -f "$ENV_FILE" "./.env"

##########################################################
################ Configuration complete ##################
##########################################################

echo "Configuring permissions..."
echo

UMBREL_DEV_FILE="${UMBREL_ROOT}/.umbrel-dev"
if [[ ! -f "${UMBREL_DEV_FILE}" ]]; then
  find "$UMBREL_ROOT" -path "$UMBREL_ROOT/app-data" -prune -o -exec chown 1000:1000 {} + || true
fi

# Create configured status
touch "${STATUS_DIR}/configured"

echo "Configuration successful"
echo "You can now start Umbrel by running:"
echo "  sudo ./scripts/start"
echo
