#!/bin/bash
set -eo pipefail
[[ $TRACE ]] && set -x

if [[ -e /usr/share/debconf/confmodule ]]; then
  . /usr/share/debconf/confmodule
fi

if [[ -r /etc/default/dokku ]]; then
  source /etc/default/dokku
fi

readonly DOKKU_ROOT="${DOKKU_ROOT:-/home/dokku}"
readonly DOKKU_LIB_ROOT="${DOKKU_LIB_PATH:-/var/lib/dokku}"

call-sshcommand() {
  if [[ -x /usr/local/bin/sshcommand ]]; then
    /usr/local/bin/sshcommand "$@"
  elif [[ -x /usr/bin/sshcommand ]]; then
    /usr/bin/sshcommand "$@"
  else
    echo "Unable to find sshcommand binary" 1>&2
    exit 1
  fi
}

setup-docker-live-restore() {
  # skip if running in docker-based installation
  if [[ "$DOKKU_INIT_SYSTEM" == "sv" ]]; then
    return
  fi

  # allow disabling via /etc/default/dokku
  if [[ "$DOKKU_LIVE_RESTORE" == "false" ]]; then
    return
  fi

  live_restore="$(docker info --format '{{ .LiveRestoreEnabled }}' || true)"
  if [ "$live_restore" = "true" ]; then
    echo "Docker live-restore is already enabled"
    return
  fi

  echo "Enabling docker live-restore"
  if [[ ! -f /etc/docker/daemon.json ]]; then
    mkdir -p /etc/docker
    echo "{}" >/etc/docker/daemon.json
  fi

  config="$(jq '. + {"live-restore": true}' /etc/docker/daemon.json)"
  echo "$config" >/etc/docker/daemon.json
  if command -v systemctl &>/dev/null; then
    if ! systemctl reload docker; then
      echo "Unable to reload docker, please reload manually" 1>&2
    fi
  else
    echo "Unable to reload docker, please reload manually" 1>&2
  fi
}

setup-user() {
  echo "Setting up dokku user"
  call-sshcommand create dokku /usr/bin/dokku
  grep -i -E "^docker" /etc/group || groupadd docker
  usermod -aG docker dokku
  mkdir -p "$DOKKU_ROOT/.ssh" "$DOKKU_ROOT/.dokkurc"
  touch "$DOKKU_ROOT/.ssh/authorized_keys"
  chown -R dokku:dokku "$DOKKU_ROOT/.ssh" "${DOKKU_ROOT}/.dokkurc"
}

setup-storage() {
  echo "Setting up storage directories"
  mkdir -p "${DOKKU_LIB_ROOT}/data" "${DOKKU_LIB_ROOT}/data/storage"
  chown dokku:dokku "${DOKKU_LIB_ROOT}/data"
}

setup-plugins() {
  echo "Deleting invalid plugins"
  if [ -f "${DOKKU_LIB_ROOT}/core-plugins/available/" ]; then
    find "${DOKKU_LIB_ROOT}/core-plugins/available/" -type d -empty -delete
  fi
  if [ -f "${DOKKU_LIB_ROOT}/core-plugins/enabled/" ]; then
    find "${DOKKU_LIB_ROOT}/core-plugins/enabled/" -type d -empty -delete
  fi
  if [ -f "${DOKKU_LIB_ROOT}/plugins/available/" ]; then
    find "${DOKKU_LIB_ROOT}/plugins/available/" -type d -empty -delete
  fi
  if [ -f "${DOKKU_LIB_ROOT}/plugins/enabled/" ]; then
    find "${DOKKU_LIB_ROOT}/plugins/enabled/" -type d -empty -delete
  fi

  echo "Setting up plugin directories"
  # should be replaced by `plugn init`
  mkdir -p "${DOKKU_LIB_ROOT}/core-plugins/available" "${DOKKU_LIB_ROOT}/plugins/available"
  mkdir -p "${DOKKU_LIB_ROOT}/core-plugins/enabled" "${DOKKU_LIB_ROOT}/plugins/enabled"
  touch "${DOKKU_LIB_ROOT}/core-plugins/config.toml" "${DOKKU_LIB_ROOT}/plugins/config.toml"

  echo "Migrating old plugins"
  find ${DOKKU_LIB_ROOT}/plugins/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | while read -r plugin; do
    if [ "$plugin" = "available" ] || [ "$plugin" = "enabled" ]; then
      continue
    elif [ -f ${DOKKU_LIB_ROOT}/plugins/$plugin/.core ]; then
      rm -rf ${DOKKU_LIB_ROOT}/plugins/$plugin
    elif [ ! -d ${DOKKU_LIB_ROOT}/plugins/available/$plugin ]; then
      mv ${DOKKU_LIB_ROOT}/plugins/$plugin ${DOKKU_LIB_ROOT}/plugins/available
    fi
  done

  db_get "dokku/nginx_enable"
  echo "Enabling all core plugins"
  find "${DOKKU_LIB_ROOT}/core-plugins/available" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | while read -r plugin; do
    if [ "$plugin" = "nginx-vhosts" ] && [ "$RET" = "false" ]; then
      echo "Skipping enable of nginx-vhosts plugin"
      continue
    elif [ ! -d "${DOKKU_LIB_ROOT}/plugins/available/$plugin" ]; then
      ln -s "${DOKKU_LIB_ROOT}/core-plugins/available/$plugin" "${DOKKU_LIB_ROOT}/plugins/available/$plugin"
      PLUGIN_PATH="${DOKKU_LIB_ROOT}/core-plugins" plugn enable "$plugin"
      PLUGIN_PATH="${DOKKU_LIB_ROOT}/plugins" plugn enable "$plugin"
    fi
  done
  find -L "${DOKKU_LIB_ROOT}/core-plugins" -type l -delete
  find -L "${DOKKU_LIB_ROOT}/plugins" -type l -delete
  chown dokku:dokku -R "${DOKKU_LIB_ROOT}/plugins" "${DOKKU_LIB_ROOT}/core-plugins"

  echo "Install all core plugins"
  dokku plugin:install --core
}

setup-sshcommand() {
  echo "Ensure proper sshcommand path"
  echo '/usr/bin/dokku' >"${DOKKU_ROOT}/.sshcommand"
  if [[ -f .ssh/authorized_keys ]]; then
    sed -i.bak 's#/usr/local/bin/dokku#/usr/bin/dokku#' "${DOKKU_ROOT}/.ssh/authorized_keys"
    rm "${DOKKU_ROOT}/.ssh/authorized_keys"
  fi
}

disable-default-vhost-path() {
  local path="$1"
  local backup_path="${path}.dokku-disabled"

  if [ ! -e "$path" ] && [ ! -L "$path" ]; then
    return
  fi

  if [ -e "$backup_path" ] || [ -L "$backup_path" ]; then
    return
  fi

  case "$path" in
    /etc/nginx/sites-enabled/*)
      rm -f "$path"
      echo "Removed conflicting nginx default at $path" 1>&2
      return
      ;;
  esac

  if [ -L "$path" ]; then
    rm -f "$path"
    echo "Removed conflicting nginx default symlink at $path" 1>&2
    return
  fi

  mv -n "$path" "$backup_path"
  echo "Disabled $path (renamed to $backup_path)" 1>&2
}

setup-default-site() {
  db_get "dokku/install_default_site"
  if [ "$RET" != "true" ]; then
    return
  fi

  local nginx_bin nginx_version major minor patch
  nginx_bin="$(command -v nginx || true)"
  if [ -z "$nginx_bin" ]; then
    return
  fi

  nginx_version="$("$nginx_bin" -v 2>&1 | cut -d'/' -f 2 | awk '{print $1}')"
  major="$(echo "$nginx_version" | awk -F. '{print $1}')"
  minor="$(echo "$nginx_version" | awk -F. '{print $2}')"
  patch="$(echo "$nginx_version" | awk -F. '{print $3}')"

  # ssl_reject_handshake requires nginx >= 1.19.4; older nginx gets the
  # HTTP-only catch-all so the SSL listen lines do not require a cert.
  local default_vhost_basename="default-site.conf"
  if [ "${major:-0}" -lt 2 ]; then
    if [ "${major:-0}" -lt 1 ] || [ "${minor:-0}" -lt 19 ] || { [ "${minor:-0}" -eq 19 ] && [ "${patch:-0}" -lt 4 ]; }; then
      default_vhost_basename="default-site-legacy.conf"
    fi
  fi

  local default_vhost_target="/etc/nginx/conf.d/00-default-vhost.conf"
  local default_vhost_source="${DOKKU_LIB_ROOT}/core-plugins/available/nginx-vhosts/templates/${default_vhost_basename}"

  if [ -e "$default_vhost_target" ]; then
    return
  fi

  if [ ! -f "$default_vhost_source" ]; then
    return
  fi

  for path in /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default /etc/nginx/conf.d/default.conf; do
    disable-default-vhost-path "$path"
  done

  echo "Installing nginx default catch-all site at $default_vhost_target"
  install -m 0644 -o root -g root "$default_vhost_source" "$default_vhost_target"

  if command -v dokku &>/dev/null; then
    dokku nginx:reload || true
  fi
}

dpkg-handling() {
  if [ -f "${DOKKU_ROOT}/VHOST" ]; then
    echo "VHOST file detected, skipping modification"
  else
    db_get "dokku/vhost_enable"
    if [ "$RET" = "true" ]; then
      db_get "dokku/hostname"
      echo "Setting VHOST contents to $RET"
      echo "$RET" >"${DOKKU_ROOT}/VHOST"
      chown dokku:dokku "${DOKKU_ROOT}/VHOST"
    fi
  fi

  if [ -z "${DEBCONF_RECONFIGURE}" ]; then
    db_get "dokku/key_file"
    if [ -f "$RET" ]; then
      call-sshcommand acl-add dokku default <"$RET" || true
    fi
  fi
}

case "$1" in
  abort-upgrade | abort-remove | abort-deconfigure) ;;

  configure)
    mandb
    [ ! -x /usr/bin/docker.io ] || ln -sf /usr/bin/docker.io /usr/local/bin/docker

    setup-user
    setup-storage

    dpkg-handling
    setup-plugins
    setup-sshcommand
    setup-docker-live-restore
    if [ -z "$2" ]; then
      setup-default-site
    fi
    ;;

  *)
    echo "postinst called with unknown argument \`$1'" >&2
    exit 1
    ;;
esac

db_stop
exit 0
