#!/usr/bin/env bash

# TODO:
# * Check that KUBECONFIG is set, maybe load automatically like before?
# * env var for native/docker mode
# * env var for local (or remote) docker image name

set -u

# If KUBECONFIG is not set, we try to find a kubeconfig file in a standard
# location.
if ! [[ -v KUBECONFIG ]]
then
  if [ -f "$(pwd)/kubeconfig/kube_config_cluster.yml" ]
  then
    export KUBECONFIG="$(pwd)/kubeconfig/kube_config_cluster.yml"
  elif [ -f "$(pwd)/backend/kubeconfig/kube_config_cluster.yml" ]
  then
    export KUBECONFIG="$(pwd)/backend/kubeconfig/kube_config_cluster.yml"
  fi
  if [[ -v KUBECONFIG ]]
  then
    echo "Local kubeconfig file found."
    echo "Setting KUBECONFIG=$KUBECONFIG"
  fi
fi

TELEPRESENCE_NOT_RUNNING=0
TELEPRESENCE_NATIVE=1
TELEPRESENCE_DOCKER=2

telepresenceRunning() {
  status=$(telepresence status | head -n 1)
  if [ "${status#*: }" == "Running" ]
  then
    echo "telepresence running"
    daemonType="${status%%:*}"
    echo "daemon type: $daemonType"
    if [ "${daemonType##* }" == "container" ]
    then
      echo "This seems to be a docker-mode daemon."
      return $TELEPRESENCE_DOCKER
    else
      echo "This seems to be a native-mode daemon."
      return $TELEPRESENCE_NATIVE
    fi
  elif [ "${status#*: }" == "Not running" ]
  then
    echo "telepresence not running"
    return $TELEPRESENCE_NOT_RUNNING
  else
    echo "Unknown telepresence state: $status"
    exit 2
  fi
}

telepresenceDns() {
  telepresence status | grep -i 'Remote IP' | awk -F': ' '{print $2}'
}

prepareDocker() {
  telepresenceRunning
  case $? in
    $TELEPRESENCE_NOT_RUNNING)
      echo "Starting telepresence daemon in docker mode."
      telepresence connect -n stackspin --docker || exit 3
      ;;
    $TELEPRESENCE_NATIVE)
      echo "Error: you want to start a docker-mode intercept, but there is a native telepresence daemon running. This is not currently supported."
      exit 3
      ;;
    $TELEPRESENCE_DOCKER)
      echo "telepresence daemon already running; connecting to it."
      telepresence connect -n stackspin --docker || exit 3
      ;;
  esac
}

prepareNative() {
  telepresenceRunning
  case $? in
    $TELEPRESENCE_NOT_RUNNING)
      echo "Starting telepresence daemon in native mode."
      telepresence connect -n stackspin || exit 3
      ;;
    $TELEPRESENCE_NATIVE)
      echo "telepresence daemon already running; connecting to it."
      telepresence connect -n stackspin || exit 3
      ;;
    $TELEPRESENCE_DOCKER)
      echo "Error: you want to start a native-mode intercept, but there is a docker telepresence daemon running. This is not currently supported."
      exit 3
      ;;
  esac
}

runBackend() {
  echo "Running dashboard backend locally and connecting to cluster."
  case $mode in
    "native")
      pushd backend > /dev/null
      source venv/bin/activate
      echo "Stopping any previous intercept for dashboard-backend..."
      telepresence leave dashboard-backend
      echo "Starting new intercept for dashboard-backend..."
      telepresence intercept dashboard-backend --service=dashboard-backend --port 5000:80 --mount=true --replace --env-file=./backend.env -- env TELEPRESENCE_MODE=native flask run --reload
      deactivate
      popd > /dev/null
      ;;
    "docker")
      echo "Stopping any previous intercept for dashboard-backend..."
      telepresence leave dashboard-backend
      telepresence intercept dashboard-backend --service=dashboard-backend --port 5000:80 --mount=true --replace --docker-run -- --dns $(telepresenceDns) -e TELEPRESENCE_MODE=docker dashboard-backend:test
  esac
}

runBackendShell() {
  echo "Running shell in the local dashboard backend environment."
  pushd backend > /dev/null
  source venv/bin/activate
  env $(xargs <backend.env) bash
  deactivate
  popd > /dev/null
}

runFrontend() {
  echo "Running dashboard frontend locally and connecting to cluster."
  case $mode in
    "native")
      pushd frontend > /dev/null
      echo "Stopping any previous intercept for dashboard-frontend..."
      telepresence leave dashboard-frontend
      telepresence intercept dashboard-frontend --service=dashboard --port 3000:80 --mount=true -- yarn start --watch --verbose
      popd > /dev/null
      ;;
    "docker")
      echo "Stopping any previous intercept for dashboard-frontend..."
      telepresence leave dashboard-frontend
      telepresence intercept dashboard-frontend --service=dashboard --port 3000:80 --mount=true --docker-run -- dashboard-frontend:test
      ;;
  esac
}

setupFrontend() {
  pushd frontend > /dev/null
  yarn install
  popd > /dev/null
}

setupBackend() {
  pushd backend > /dev/null
  if ! [ -d venv ]
  then
    python3 -m venv venv
  fi
  source venv/bin/activate
  pip install -r requirements.txt
  deactivate
  popd > /dev/null
}

setupCluster() {
  telepresence helm install -f telepresence-values.yaml
}

cleanCluster() {
  telepresence uninstall --all-agents
  helm uninstall -n ambassador traffic-manager
}

if [ $# -eq 0 ]
then
  echo "No command given. See README.md for help."
  exit 1
fi

if [ "$1" == "reset" ]
then
  telepresence quit -s
  kubectl rollout restart -n ambassador deploy/traffic-manager
  exit 0
fi

if [ "$1" == "backend-shell" ]
then
    runBackendShell
    exit 0
fi

if [ $# -eq 1 ]
then
  mode="native"
else
  mode=$2
fi

if [ $# -eq 2 ] && [ "$1" == "cluster" ] && [ "$2" == "clean" ]
then
  echo "Removing all development modifications from remote cluster..."
  cleanCluster
  exit 0
fi

if [ $# -eq 2 ] && [ "$2" == "pause" ]
then
  case $1 in
    "backend")
      kubectl set image -n stackspin deploy/dashboard-backend backend=docker.io/rancher/mirrored-pause:3.6
      exit 0
      ;;
    *)
      echo "Unknown pause command: $1 $2"
      exit 4
  esac
fi

if [ $# -eq 2 ] && [ "$2" == "setup" ]
then
  case $1 in
    "backend")
      setupBackend
      exit 0
      ;;
    "frontend")
      setupFrontend
      exit 0
      ;;
    "cluster")
      setupCluster
      exit 0
      ;;
    *)
      echo "Unknown setup command: $1 $2"
      exit 4
  esac
fi

case $mode in
  "docker")
    prepareDocker
    ;;
  "native")
    prepareNative
    ;;
  *)
    echo "Unknown mode (should be docker or native): $mode"
    exit 4
esac

case $1 in
  "backend")
    runBackend
    ;;
  "frontend")
    runFrontend
    ;;
  *)
    echo "Unknown command: $1"
    exit 4
esac
