#!/usr/bin/env bash
set -e

START_TIME=`date +%s`
CWD="${0%/*}"
LIB=$CWD/../lib
VAR=$CWD/../var
OUT=$CWD/../out
PORT=2000

# parse arguments
otherargs=()
while [[ "$#" > 0 ]]; do case $1 in
  --ci) ci=1;;
  -d|--deploy) deploy=1;;
  --deploy-mcd-only) deploy_mcd_only=1;;
  --deploy-scd-only) deploy_scd_only=1;;
  --fast) fast=1;;
  -p|--port) PORT="$2"; shift;;
  --reset-chaindata) reset_chaindata=1;;
  -s|--snapshot) snapshot="$2"; shift;;
  --throw-revert) throw_revert=1;;
  -u | --skip-update) SKIP_SUBMODULE_UPDATE=1;;
  --verbose) verbose=1;;
  *) otherargs+=($1);;
esac; shift; done

# Check if a testnet is already running
if ! nc -z 127.0.0.1 $PORT; then
  mkdir -p $VAR

  if [ "$reset_chaindata" ]; then
    echo "Clearing chaindata."
    rm -rf $VAR/chaindata
    mkdir $VAR/chaindata
  else
    if [ ! -e $VAR/chaindata ]; then
      snapshot="default"
    fi

    if [ "$snapshot" ]; then
      echo "Loading snapshots/$snapshot."
      rm -rf $VAR/chaindata
      mkdir $VAR/chaindata
      tar xzf $CWD/../snapshots/$snapshot.tgz -C $VAR/chaindata
    else
      echo "Using existing chaindata on disk."
    fi
  fi

  if [ $fast ]; then
    export SKIP_BUILD_IF_ALREADY_BUILT=1
    export SKIP_SUBMODULE_UPDATE=1
  fi

  if [ -n "$SKIP_SUBMODULE_UPDATE" ]; then
    echo "Skipping git submodule update."
  else
    git submodule update --init --recursive
  fi

  # Configure seth
  export ETH_GAS=${ETH_GAS:-"6721975"} # Ganache's default block gas limit
  export SETH_STATUS=yes
  export ETH_RPC_ACCOUNTS=yes # Don't use ethsign
  export ETH_RPC_URL=http://127.1:$PORT

  # Start a testnet
  GANACHE_CLI=$CWD/../node_modules/.bin/ganache-cli
  if [ ! -e $GANACHE_CLI ]; then
    echo "Installing Ganache..."
    cd $CWD/..
    yarn install
    cd -
  fi

  echo "Starting Ganache..."
  ganache_args=(
    $GANACHE_CLI
    -i 999
    -p $PORT
    -a 1000
    -m "hill law jazz limb penalty escape public dish stand bracket blue jar"
    --db $VAR/chaindata
  )

  if [ ! $throw_revert ]; then
    ganache_args+=(--noVMErrorsOnRPCResponse)
  fi

  if [ $verbose ]; then
    "${ganache_args[@]}" 2>&1 & netpid=$!
  else
    "${ganache_args[@]}" > $VAR/ganache.out 2>&1 & netpid=$!
  fi

  # Wait for the testnet to become responsive
  until curl -s -o/dev/null "$ETH_RPC_URL"; do
    sleep 1
    if [ -z "$(ps -p $netpid -o pid=)" ]; then
      echo "Ganache stopped running. Check var/ganache.out for errors."
      exit 1
    fi
  done

  # Stop the testnet when this script exits
  trap "kill $netpid" EXIT

  # Finish configuring seth with settings from running testnet
  export ETH_FROM=$(seth rpc eth_coinbase)

  # Deploy contracts
  if [ $deploy ]; then
    if [ "$SKIP_BUILD_IF_ALREADY_BUILT" ]; then
      echo "Skipping build of dapps that are already built."
    fi
    deploy_args=($CWD/deploy)
    if [ "$deploy_mcd_only" ]; then deploy_args+=(--mcd-only); fi
    if [ "$deploy_scd_only" ]; then deploy_args+=(--scd-only); fi
    "${deploy_args[@]}"
  fi

  END_TIME=`date +%s`
  ELAPSED=`echo $END_TIME - $START_TIME | bc`
  echo "Launched testchain in" $ELAPSED "seconds."
else
  echo "Testchain is already running on port $PORT."
fi


if [ "$ci" ]; then
  # Proceed to the command given
  ${otherargs[@]}
else
  # The testnet will continue to run with its deployed contracts
  # until the user confirms it should shut down.
  echo "Press Ctrl-C to stop the testchain."
  while true; do read; done
fi
