#!/usr/bin/env bash

set -e

# For mac support
if ! which realpath >/dev/null; then
  realpath() {
    node -p "require('fs').realpathSync('${1}')"
  }
fi

dry() {
  [ "${DRY_RUN:-0}" != "0" ]
}

dry-wrap() {
  if ! dry; then
    "${@}"
  else
    >&2 echo "+ ${@}"
  fi
}

install-dev() {
  if which yarn >/dev/null; then
    dry-wrap yarn add --dev "${1}"
  else
    dry-wrap npm install --save-dev "${1}"
  fi
}

# $1 = source
# $2 = dest
make-symlink() {
  local SOURCE="$(realpath "${1}")"
  local TARGET="${2}"

  if ! [ -e "${SOURCE}" ]; then
    >&2 echo "SOURCE (${SOURCE}) does not exist"

    return 1
  fi

  if [ -L "${TARGET}" ]; then
    local CURRDEST="$(realpath "${TARGET}")"

    if [ "${CURRDEST}" = "${SOURCE}" ]; then
      if dry; then
        >&2 echo "Not updating symlink ${TARGET} because it already points to ${SOURCE}"
      fi

      return 0
    else
      >&2 echo "Removing the existing symlink ${TARGET}->${CURRDEST} to replace it with ${TARGET}->${SOURCE}"

      dry-wrap rm "${TARGET}"
    fi
  elif [ -e "${TARGET}" ]; then
    >&2 echo "Cowardly refusing to update existing non-symlink \"${TARGET}\""

    return 0
  fi

  dry-wrap ln -rs "${SOURCE}" "${TARGET}"
  SYMLINK_CREATED=1
}

rm-old-symlink() {
  local SOURCE="${1}"
  local TARGET="${2}"

  local RSOURCE="$(realpath "${1}")"
  local RTARGET="$(realpath "${2}")"

  if [ -L "${TARGET}" ] && ( [ "${RTARGET}" = "${SOURCE}" ] || [ "${RTARGET}" = "${RSOURCE}" ] ); then
    dry-wrap rm "${TARGET}"
  fi
}

link-test-deps() {
  local DEP_DIR=
  local HOOK_BASE=
  local HUSKY_SYMLINK_CREATED=0
  local REPODIR="$(realpath "$(dirname "$(realpath "${BASH_SOURCE[0]}")")/..")"
  local REPONAME="$(node -p "require('${REPODIR}/package.json').name")"
  local TEMPLATES_DIR=
  local TEST_DIR="./test"

  DEP_DIR="./node_modules/${REPONAME}"
  TEMPLATES_DIR="${DEP_DIR}/configuration-templates"

  if [ ! -e "./node_modules/${REPONAME}" ]; then
    install-dev "${REPONAME}"
  fi

  for i in eslintrc.js lint-staged.config.js mocharc.js nyc.config.js prettierrc.js; do
    OUTPUT="${i}"

    if echo $i | grep -E 'rc\.js$' 2>/dev/null 1>&2; then
      OUTPUT=".${OUTPUT}"
    fi

    make-symlink "${TEMPLATES_DIR}/${i}" "${OUTPUT}"
  done

  dry-wrap mkdir -p "${TEST_DIR}"
  make-symlink "${TEMPLATES_DIR}/add-deps-global.js" "${TEST_DIR}/add-deps-global.js"

  # remove old, no longer used symlinks
  rm-old-symlink "${TEMPLATES_DIR}/huskyrc.js" .huskyrc.js

  dry-wrap mkdir -p "./.husky"

  SYMLINK_CREATED=0

  for HOOK in "${TEMPLATES_DIR}/husky-7-dir/"*; do
    HOOK_BASE="$(basename "${HOOK}")"

    if ! [ -d "${HOOK_BASE}" ]; then
      make-symlink "${HOOK}" "./.husky/${HOOK_BASE}"
    fi
  done

  if [ "${SYMLINK_CREATED}" = "1" ]; then
    HUSKY_SYMLINK_CREATED=1
  fi

  unset SYMLINK_CREATED

  if [ "$(node -p "((require('./package.json') || {}).scripts || {}).prepare")" = "undefined" ]; then
    >&2 echo 'Be sure to add script "prepare" with value "husky install", see below to copy/paste'
    >&2 echo '  "prepare": "husky install"'
  fi

  if ! [ -d ".husky/_" ] || [ "${HUSKY_SYMLINK_CREATED}" = "1" ]; then
    >&2 echo 'Be sure to run prepare like so:'
    >&2 echo '  yarn prepare'
  fi
}

link-test-deps "$@"
