#!/bin/sh

yellow="\e[33m"
reset="\e[0m"

# This is the babushka bootstrap script. To install babushka, you can
# execute it in a terminal:
#
# sh -c "`curl https://babushka.me/up`"

# This is the version to install. It defaults to 'stable' and can be customised
# by setting the VERSION env var to any git ref (branch, tag, commit):
#
# VERSION=refspec sh -c "`curl https://babushka.me/up`"
if [ -n "$VERSION" ]; then
  ref=$VERSION
else
  ref="stable"
fi

# The install repo can be customised by setting the REPO env var:
#
#
if [ -n "$REPO" ]; then
  repo=$REPO
fi


# Can't use $HOME, because sometimes it's not set.
# Can't use ~, because it depends on $HOME to expand.
# Can't use ~$(whoami) directly, because it doesn't expand inline.
# So: write a string in which ~$(whoami) is expanded, and run it in a subshell.
home=$(sh -c "echo ~$(whoami)")

from="https://github.com/benhoskings/babushka/archive/$ref.tar.gz"
to="$home/.babushka/bootstrap"

interactive=$([ -t 0 ] && echo 'true' || echo 'false')

true_with() { echo -e "\n$1"; true; }
false_with() { echo -e "\n$1"; false; }

has() {
  type "$1" >/dev/null 2>&1
}

pkg_manager() {
  managers="aptitude apt-get brew pacman yum pkg_add"
  for manager in ${managers}; do
    has "$manager" && echo "$manager" && exit
  done
}

update_manager() {
  case $(pkg_manager) in
    apt-get) apt-get update -qqy ;;
    aptitude) aptitude -y update ;;
    brew) brew update ;;
    pacman) pacman --sync --refresh ;;
    yum) true ;;
    pkg_add) true ;;
    *)
  esac
}

install_pkgs() {
  case $(pkg_manager) in
    apt-get) apt-get install -qqy $1 ;;
    aptitude) aptitude -y install $1 ;;
    brew) brew install $1 ;;
    pacman) pacman --sync --noconfirm --noprogressbar $1 ;;
    yum) yum -y install $1 ;;
    pkg_add) pkg_add -r $1 ;;
    *)
  esac
}

logo() {
cat <<"LOGO"

.       .           .   .
|-. ,-. |-. . . ,-. |-. | , ,-.
| | ,-| | | | | `-. | | |<  ,-|
^-' `-^ ^-' `-^ `-' ' ' ' ` `-^
LOGO
}

check() {
  if ! has 'curl'; then
    if ! has $(pkg_manager); then
      echo "Sorry, you don't have curl installed, and I couldn't find a package manager I recognise."
      has 'wget' && echo "(You do have wget, but the version on most stock VPS images doesn't do SSL.)"
      false
    elif [ $(whoami) != 'root' ] && [ $(pkg_manager) != 'brew' ]; then
      false_with "You don't have curl installed. I can install it via $(pkg_manager), but only when running as root."
    else
      true
    fi
  elif ! has 'ruby'; then
    if ! has $(pkg_manager); then
      false_with "Sorry, you don't have ruby installed, and I couldn't find a package manager I recognise."
    elif [ $(whoami) != 'root' ] && [ $(pkg_manager) != 'brew' ]; then
      false_with "You don't have ruby installed. I can install it via $(pkg_manager), but only when running as root."
    else
      true
    fi
  else
    true
  fi
}

welcome() {
  echo ""
  echo "Hi there :)"
  echo ""
  echo "Let's get down to business - first, pulling a tarball of babushka from"
  echo "https://github.com. Then, using it to run \"babushka babushka\", which"
  echo "installs or updates babushka and git as required."
  if [ -n "$repo" ]; then
    echo ""
    echo "I'll install from this repo:"
    echo "  $repo"
  fi
  echo ""

  if has 'curl'; then
    echo "- You already have curl."
  else
    echo "- You don't have curl installed, so we'll install it first (using $(pkg_manager))."
    has 'wget' && echo "  (You do have wget, but the version on most stock VPS images doesn't do SSL.)"
  fi

  if has 'ruby'; then
    echo "- You already have ruby $(ruby --version | awk '{print $2}')."
  else
    echo "- You don't have ruby installed, so we'll install it (using $(pkg_manager))."
  fi

  if [ "$interactive" = 'false' ]; then
    true
  else
    echo ""
    confirmed=""
    if [ -n "$ZSH_VERSION" ]; then
      vared -p "Sound good? [y/N] " confirmed
    elif [ -n "$BASH_VERSION" ]; then
      read -e -p "Sound good? [y/N] " confirmed
    else
      read -p "Sound good? [y/N] " confirmed
    fi
    case $confirmed in
      "y"*) true;;
      "Y"*) true;;
      *)    false;;
    esac
  fi
}

install_pkgs_if_required() {
  if has 'ruby' && has 'curl'; then
    true # already installed
  else
    pkgs="$(has 'curl' || echo 'curl') $(has 'ruby' || echo 'ruby')"
    echo ""
    echo "First we need to install $(echo $pkgs | sed 's/ / \& /') (via $(pkg_manager))."
    update_manager
    install_pkgs "$pkgs"
    if ! has 'ruby' || ! has 'curl'; then
      false_with "Argh, the install failed."
    else
      echo ""
      echo "- ruby $(ruby --version | awk '{print $2}') is present at $(which ruby)."
      echo "- curl is present at $(which curl)."
      true
    fi
  fi
}

clean_up_install_dir() {
  mkdir -p "$home/.babushka" &&
  cd "$home/.babushka" &&
  rm -rf "bootstrap"
  cd "$home"
}

create_install_dir() {
  clean_up_install_dir &&
  mkdir -p "$to" &&
  cd "$to"
}

stream_tarball() {
  echo ""
  echo "Right, downloading a tarball of babushka @ $ref."
  curl -L -\# "$from" | tar -zxf - --strip-components 1
}

handle_install() {
  echo "Invoking babushka $(cd "$to" && bin/babushka.rb --version) to handle the install."
  echo ""
  ruby "$to/bin/babushka.rb" meet babushka \
    version="$ref" \
    $([ -n "$repo" ] && echo "from=$repo") \
    $([ "$interactive" = 'true' ] || echo '--defaults')
  [ $? -eq 0 ]
}

on_install_success() {
  clean_up_install_dir

  echo ""
  echo "All installed! If you're new, the basic idea is 'babushka <dep name>', e.g.:"
  echo "  babushka babushka   # install/update babushka itself (i.e. what just happened)"
  echo "  babushka homebrew   # set up homebrew on your Mac"
  echo ""
  echo "You can run your own deps like this from ~/.babushka/deps & ./babushka-deps."
  echo ""
  echo "A dep is a unit of work that also knows how to check if its job has already been"
  echo "done (if it's already "met"). Here are the details: babushka.me/how-deps-work"
  echo ""
  echo "You can run public deps (if you trust the author) by prefixing with their"
  echo "github username; they're cloned from http://github.com/<name>/babushka-deps."
  echo "  babushka benhoskings:Sinatra.tmbundle   # also installs TextMate if required"
  echo "  babushka conversation:coffeescript.src  # pulls in node.js if required, etc."
  echo ""
  echo "Resources:"
  echo "  babushka --help"
  echo "  babushka.me"
  echo "  babushka.me/rdoc"
  echo "  babushka.me/mailing_list"
  true
}

on_install_failure() {
  echo ""
  echo "Something went wrong during the install."
  echo ""
  echo "If you fix the problem, you can re-run the install with:"
  echo "  ruby $to/bin/babushka.rb babushka"
  echo ""
  echo "There's a full log in ~/.babushka/logs/babushka. Would you mind"
  echo "emailing it to ben@hoskings.net to help improve the installation"
  echo "process? Thanks a lot."
  false
}

do_bootstrap() {
  install_pkgs_if_required &&
  create_install_dir &&
  stream_tarball &&
  handle_install && on_install_success || on_install_failure
}

logo
if check; then
  if welcome; then
    do_bootstrap
  else
    echo ""
    echo "OK, maybe another time. :)"
  fi
fi
