#!/usr/bin/env bash
#!/usr/bin/env ruby

# A total hack, but this file is both a valid ruby script and a bash script.
=begin 2>/dev/null

# From here on in, it is all bash until the last line

help_and_exit() {
  cat <<EOF
A type checker for Ruby

Usage:
  srb                                 Same as "srb t"
  srb (init | initialize)             Initializes the \`sorbet\` directory
  srb rbi [options]                   Manage the \`sorbet\` directory
  srb (t | tc | typecheck) [options]  Typechecks the code

Options:
  -h, --help     View help for this subcommand.
  --version      Show version.

For full help:
  https://sorbet.org
EOF
  exit 1
}

subcommand=$1
shift

# /path/to/gems/sorbet-0.0.1/bin/srb
srb_path="${BASH_SOURCE[0]}"

compute_md5() {
  if command -v md5sum > /dev/null; then
    md5sum "$1"
  elif command -v md5 > /dev/null; then
    md5 -r "$1"
  else
    # this is quite a bit slower
    ruby -e 'require "digest"; puts Digest::MD5.hexdigest(File.read(ARGV[0]))' "$1"
  fi
}

typecheck() {
  args=("$@")
  cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/sorbet/gem-rbis"

  if [ -z "$SRB_SKIP_GEM_RBIS" ] && [ -f Gemfile.lock ]; then
    [ -d "$cache_dir" ] || mkdir -p "$cache_dir"
    cache_hash=$(compute_md5 Gemfile.lock | awk '{ print $1 }')
    cache_file="${cache_dir}/${cache_hash}"
    if [ ! -f "$cache_file" ]; then
      "$0" rbi find-gem-rbis > /dev/null
    fi
    args+=("@$cache_file")
  fi

  if [ -n "$SRB_SORBET_EXE" ]; then
    # shellcheck disable=SC2086
    "$SRB_SORBET_EXE" "${args[@]}"
  else
    # We're using bash string operations here to avoid forking.
    # Using dirname / basename / etc. would mean ~15ms for each call.

    # /path/to/gems/sorbet-0.0.1
    without_bin_srb="${srb_path%/bin/srb}"
    # -0.0.1
    version_suffix="${without_bin_srb##*/sorbet}"
    # /path/to/gems
    gems_path="${without_bin_srb%/sorbet*}"

    # /path/to/gems/sorbet-static-0.0.1-darwin-17/libexec/sorbet
    # (assumes people only have one platform-dependent gem installed per version)
    guess_sorbet=("$gems_path/sorbet-static$version_suffix"*/libexec/sorbet)

    if [[ -f "${guess_sorbet[0]}" ]]; then
      sorbet="${guess_sorbet[0]}"
    else
      # 0.0.1
      version="${version_suffix#-}"
      # Resort to locating using the GEM_PATH, this takes ~200ms
      sorbet="$(VISUAL=echo gem open sorbet-static -v "${version}")/libexec/sorbet"
    fi

    # if we still don't know the sorbet binary
    # perhaps this is the java platform
    if ! [[ -f "${sorbet}" ]]; then
      if gem env platform | grep -q "java"; then
        # certain platforms (i.e. java) include multiple binaries
        # mac.sorbet & linux.sorbet -- since they can't use the host platform (i.e. darwin or linux)
        # to collect the correct sorbet binary
        case "$(uname -s)" in
        Linux*)     prefix="linux.";;
        Darwin*)    prefix="mac.";;
        *)          prefix=""
        esac

        guess_sorbet=("$gems_path/sorbet-static$version_suffix"*/libexec/"${prefix}sorbet")
        if [[ -f "${guess_sorbet[0]}" ]]; then
          sorbet="${guess_sorbet[0]}"
        fi

      fi
    fi

    # shellcheck disable=SC2086
    exec "${sorbet}" "${args[@]}"
  fi
}

# Dynamically computing the path to the srb-rbi script lets this script work
# the same way in local development and when packaged as a gem. Either:
#
# /path/to/gems/sorbet-0.0.1/bin/srb-rbi
# path/to/bin/srb-rbi
srb_rbi_path="$srb_path-rbi"

case $subcommand in
  "initialize" | "init")
    "$srb_rbi_path" "init"
    ;;

  "rbi")
    "$srb_rbi_path" "$@"
    ;;

  "" | "typecheck" | "tc" | "t")
    if [ ! -d sorbet ] && [ "$#" -eq 0 ]; then
        echo "No sorbet/ directory found. Maybe you want to run 'srb init'?"
        echo
        help_and_exit
    fi
    typecheck "$@"
    ;;

  "--version")
    typecheck --version
    ;;

  *)
    echo "Unknown subcommand \`$subcommand\`"
    help_and_exit
esac

exit $?
# The closing comment for ruby to be ok with this file
=end
exec([__FILE__, __FILE__], *ARGV)
