#!/bin/bash

fail() {
  echo "${@}" >&2
  exit 1
}

on_tag() {
  if [ -n "$CURRENT_TAG" ]; then
    echo "${@}"
    eval "${@}"
    return $?
  else
    return 0
  fi
}

fail_on_error() {
  "${@}"

  exit=$?
  if [ "$exit" -ne "0" ]; then
    fail "${@} exited with $exit"
  fi

  return 0
}

verify_environment() {
  if [ -z "$TRAVIS_OS_NAME" ]; then
    fail "\$TRAVIS_OS_NAME is not set or empty."
  fi
}

verify_linux_environment() {
  if [ -z "$ARCH" ]; then
    fail "\$ARCH is not set or empty."
  fi

  if [ -z "$ARCH_CMD" ]; then
    fail "\$ARCH_CMD is not set or empty."
  fi
}

on_os() {
  os="$1"
  shift

  verify_environment

  if [ "$TRAVIS_OS_NAME" = "$os" ]; then
    echo "${@}"
    eval "${@}"
    return $?
  else
    return 0
  fi
}

on_linux() {
  fail_on_error on_os "linux" "${@}"
}

on_osx() {
  fail_on_error on_os "osx" "${@}"
}

prepare_system() {
  on_linux 'echo '"'"'{"ipv6":true, "fixed-cidr-v6":"2001:db8:1::/64"}'"'"' | sudo tee /etc/docker/daemon.json'
  on_linux sudo service docker restart

  on_osx brew update
}

build() {
  with_build_env 'make std_spec clean'
  with_build_env 'make crystal std_spec compiler_spec docs'
  with_build_env 'find samples -name "*.cr" | xargs -L 1 ./bin/crystal build --no-codegen'
  with_build_env './bin/crystal tool format --check samples spec src'
}

prepare_build() {
  on_linux verify_linux_environment

  on_linux docker pull "jhass/crystal-build-$ARCH"

  on_osx brew install llvm crystal-lang
}

with_build_env() {
  command="$1"

  # Ensure non GMT timezone
  export TZ="America/New_York"

  on_linux verify_linux_environment
  on_linux docker run \
    --rm -t \
    -u $(id -u) \
    -v $(pwd):/mnt \
    -w /mnt \
    -e LIBRARY_PATH="${ARCH_LIBRARY_PATH:-/usr/lib/crystal/lib/}" \
    -e CRYSTAL_CACHE_DIR="/tmp/crystal" \
    "jhass/crystal-build-$ARCH" \
    "$ARCH_CMD" /bin/bash -c "'$command'"

  on_osx sudo systemsetup -settimezone $TZ
  on_osx PATH="/usr/local/opt/llvm/bin:\$PATH" \
    CRYSTAL_CACHE_DIR="/tmp/crystal" \
    /bin/bash -c "'$command'"

}

usage() {
  echo -e "bin/ci [-h|--help] command [parameter ...]"
  echo -e ""
  echo -e "Helper script to prepare and run the testsuite on Travis CI."
  echo -e ""
  echo -e "Commands:"
  echo -e "  prepare_system          setup any necessaries repositories etc."
  echo -e "  prepare_build           download and extract any dependencies needed for the build"
  echo -e "  build                   run specs, build crystal, run format check, build samples, build the docs"
  echo -e "  with_build_env command  run command in the build environment"
  echo -e "  help                    display this"
  echo -e ""
}

command="$1"
shift
case $command in
  prepare_system)
    prepare_system
    ;;
  prepare_build)
    prepare_build
    ;;
  with_build_env)
    target_command="${@}"
    with_build_env "$target_command"
    ;;
  build)
    build
    ;;
  -h|--help|help)
    usage
    ;;
  *)
    if [ -n "$command" ]; then
      fail "Unknown command $command"
    else
      usage
      exit 1
    fi
    ;;
esac
