#!/usr/bin/env bash

__origin="${BASH_SOURCE:-$_}"
__origin="${__origin%/*}"
source "${__origin}/utility_gems"
source "${__origin}/utility_logging"
source "${__origin}/utility_package"
source "${__origin}/utility_system"
unset  __origin

printenv_null()
{
  if printenv --null >/dev/null 2>/dev/null
  then
    printenv --null
  else
    # this messes with escape sequences but allows new lines in variables
    printenv | __rvm_sed '/=/ { s/=.*$//; p; }; d;' | while read name
    do
      zero="\0"
      eval "eval \"printf '%b' '$name=\$$name$zero'\""
    done
  fi
}

__rvm_strings()
{
  typeset strings ruby_strings

  ruby_strings=($(echo ${rvm_ruby_args:-$rvm_ruby_string}))

  for rvm_ruby_string in "${ruby_strings[@]}" ; do
    strings="$strings $(__rvm_select ; echo $rvm_ruby_string)"
  done

  echo $strings

  return 0
}

# Return a list of directories under a given base path.
# Derived from rvm_ruby_string.
__rvm_ruby_string_paths_under()
{
  typeset __search_path part parts IFS
  IFS=" "

  __search_path="${1%/}" # Strip off any trailing slash

  if [[ -n "${ZSH_VERSION:-}" ]]
  then parts=(${=rvm_ruby_string//-/ })
  else parts=(${rvm_ruby_string//-/ }) # Strip white space.
  fi

  echo "$__search_path"
  for part in "${parts[@]}"
  do
    __search_path="$__search_path/$part"
    echo "$__search_path"
  done
}

# Output the current ruby's rvm source path.
__rvm_source_dir()
{
  if [[ ${rvm_ruby_selected_flag:-0} -eq 0 ]]
  then __rvm_select
  fi

  if [[ -z "$rvm_ruby_src_path" ]]
  then
    rvm_error "No source directory exists for the default implementation."
  else
    echo "$rvm_ruby_src_path"
  fi

  return 0
}

# Strip whitespace and normalize it all.
__rvm_strip()
{
  __rvm_sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[[:space:]]\{1,\}/ /g'
  return $?
}

# remove all entries from $PATH starting with $1
__rvm_remove_from_path()
{
  export PATH
  typeset _value
  _value="${1//+(\/)//}"

  # remove multiple slashes https://github.com/wayneeseguin/rvm/issues/1364
  if
    [[ "$PATH" =~ "//" ]]
  then
    if [[ "${_system_type}" = "Darwin" ]]
    then PATH="$(sed -E 's#/+#/#g' <<<$PATH)"
    else PATH="$(sed -r 's#/+#/#g' <<<$PATH)"
    fi
  fi

  if
    __rvm_string_match ":$PATH:" "*:${_value}:*"
  then
      typeset -a _path
      _path=()
      __rvm_custom_separated_array _path : "${PATH}"
      __rvm_remove_from_array _path "${_value}" "${_path[@]}"
      __rvm_join_array PATH : _path
  fi
}

__rvm_add_to_path()
{
  export PATH

  if (( $# != 2 )) || [[ -z "$2" ]]
  then
    rvm_error "__rvm_add_to_path requires two parameters"
    return 1
  fi

  __rvm_remove_from_path "$2"
  case "$1" in
    prepend) PATH="$2:$PATH" ;;
    append)  PATH="$PATH:$2" ;;
    #*) anything else will just remove it from PATH - not adding back
  esac

  if
    [[ -n "${rvm_user_path_prefix:-}" ]]
  then
    __rvm_remove_from_path "${rvm_user_path_prefix}"
    PATH="${rvm_user_path_prefix}:$PATH"
  fi
  builtin hash -r
}

rvm_is_a_shell_function()
{
  typeset _message
  if
    (( ${rvm_is_not_a_shell_function:-0} )) &&
    [[ "${1:-}" != "no_warning" ]]
  then
    if rvm_pretty_print stderr
    then rvm_log "" # newline when error is shown to user
    fi
    if rvm_pretty_print stderr
    then rvm_log "RVM is not a function, selecting rubies with '${rvm_error_clr:-}rvm use ...${rvm_notify_clr:-}' will not work." >&2
    else rvm_error "RVM is not a function, selecting rubies with 'rvm use ...' will not work."
    fi
    rvm_warn '
You need to change your terminal emulator preferences to allow login shell.
Sometimes it is required to use `/bin/bash --login` as the command.
Please visit https://rvm.io/integration/gnome-terminal/ for a example.
'
  fi
  return ${rvm_is_not_a_shell_function:-0}
}

__rvm_detect_xcode_version()
{
  typeset version_file
  for version_file in \
    /Applications/Xcode.app/Contents/version.plist \
    /Developer/Applications/Xcode.app/Contents/version.plist
  do
    if
      [[ -f $version_file ]]
    then
      if
        [[ -x /usr/libexec/PlistBuddy ]]
      then
        /usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $version_file
      else
        __rvm_sed -n '/<key>CFBundleShortVersionString<\/key>/{n; s/^.*>\(.*\)<.*$/\1/; p;}' < $version_file
      fi
      return 0
    fi
  done
  if
    builtin command -v xcodebuild >/dev/null
  then
    xcodebuild -version | __rvm_sed -n '/Xcode/ {s/Xcode //; p;}'
    return 0
  fi
  return 1
}

__rvm_detect_xcode_version_at_least()
{
  typeset __xcode_version="$(__rvm_detect_xcode_version)"
  [[ -n "$__xcode_version" ]] || return 0
  __rvm_version_compare "$__xcode_version" -ge "$1" || return $?
  true # for OSX
}

# TODO: better semver support
__rvm_version_sort()
{
  LC_ALL=C sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n
}

__rvm_version_compare()
{
  typeset first
  first="$( printf "%b" "$1\n$3\n" | __rvm_version_sort | head -n1 )"
  # first is the lower
  case "$2" in
    (-eq|==|=)
      [[ "$1" == "$3" ]] || return $?
      ;;
    (-ne|!=)
      [[ "$1" != "$3" ]] || return $?
      ;;
    (-gt|\>)
      [[ "$first" == "$3" && "$1" != "$3" ]] || return $?
      ;;
    (-ge|\>=)
      [[ "$first" == "$3" || "$1" == "$3" ]] || return $?
      ;;
    (-lt|\<)
      [[ "$first" == "$1" && "$1" != "$3" ]] || return $?
      ;;
    (-le|\<=)
      [[ "$first" == "$1" || "$1" == "$3" ]] || return $?
      ;;
    (*)
      rvm_error "Unsupported operator '$2'."
      return 1
      ;;
  esac
  return 0
}

# parse comma separated string into an array
# Ex. __rvm_custom_separated_array strings - ruby_string
# adds all elements from `ruby_string` to `strings` array
__rvm_custom_separated_array()
{
  typeset IFS
  IFS=$2
  if [[ -n "${ZSH_VERSION:-}" ]]
  then eval "$1+=( \${=3} )"
  else eval "$1+=( \$3 )"
  fi
}

__rvm_remove_from_array()
{
  typeset _array_name _search _iterator
  typeset -a _temp_array
  _array_name="$1"
  _search="$2"
  shift 2
  _temp_array=()
  for _iterator
  do
    __rvm_string_match "$_iterator" "$_search" || _temp_array+=( "$_iterator" )
  done
  eval "$_array_name=( \"\${_temp_array[@]}\" )"
}

__rvm_join_array()
{
  typeset IFS
  IFS="$2"
  eval "$1=\"\${$3[*]}\""
}

__rvm_add_once()
{
  typeset IFS
  IFS="|"
  eval "[[ \"${IFS}\${${1}[*]}${IFS}\" == \*\"${IFS}\${2}${IFS}\"\* ]] || ${1}+=( \"\${2}\" )"
}

__rvm_find_first_file()
{
  typeset _first_file _variable_first_file __file_enum
  _first_file=""
  _variable_first_file="$1"
  shift

  for __file_enum in "$@"
  do
    if
      [[ -f "$__file_enum" ]]
    then
      eval "$_variable_first_file=\"\$__file_enum\""
      return 0
    fi
  done
  eval "$_variable_first_file=\"\""
  return 1
}

file_exists_at_url()
(
  if
    [[ -n "${1:-}" ]]
  then
    unset curl
    __rvm_curl --silent --insecure --location --list-only \
      --max-time ${rvm_max_time_flag:-5} --head "$1" 2>&1 |
      __rvm_grep -E 'HTTP/[0-9\.]+ 200 OK' >/dev/null 2>&1 ||
    {
      typeset __ret=$?
      case ${__ret} in
        (28)
          rvm_warn "RVM was not able to check existence of remote files with timeout of ${rvm_max_time_flag:-3} seconds
you can increase the timeout by setting it in ~/.rvmrc => rvm_max_time_flag=10"
          ;;
      esac
      return ${__ret}
    }
  else
    rvm_warn "Warning: URL was not passed to file_exists_at_url"
    return 1
  fi
)

__rvm_try_sudo()
(
  typeset -a command_to_run
  typeset sudo_path sbin_path missing_paths
  command_to_run=( "$@" )
  (( UID == 0 )) ||
  case "$rvm_autolibs_flag_number" in
    (0)
      rvm_debug "Running '$*' would require sudo."
      return 0
      ;;
    (1)
      rvm_warn  "Running '$*' would require sudo."
      return 0
      ;;
    (2)
      rvm_requiremnts_fail error "Running '$*' would require sudo."
      return 1
      ;;
    (*)
      if
        [[ "${_system_name} ${_system_version}" == "Solaris 10" ]] &&
        ! __rvm_which sudo >/dev/null 2>&1
      then
        sudo_path=/opt/csw/bin/
      else
        sudo_path=""
      fi
      if
        __rvm_which ${sudo_path}sudo >/dev/null 2>&1
      then
        missing_paths=""
        for sbin_path in /sbin /usr/sbin /usr/local/sbin
        do
          if [[ -d "${sbin_path}" ]] && [[ ! ":$PATH:" =~ ":${sbin_path}:" ]]
          then missing_paths+=":${sbin_path}"
          fi
        done
        if [[ -n "${missing_paths}" ]]
        then command_to_run=( /usr/bin/env PATH="${PATH}${missing_paths}" "${command_to_run[@]}" )
        fi
        command_to_run=( ${sudo_path}sudo -p "%p password required for '${command_to_run[*]}': " "${command_to_run[@]}" )
      else
        rvm_requiremnts_fail error "Running '$*' would require sudo, but 'sudo' is not found in PATH!"
        return 1
      fi
      ;;
  esac
  "${command_to_run[@]}" || return $?
)

__rvm_run_wrapper()
( # ( = subprocess
  file="$1"
  action="${2:-}"
  shift 2
  rubies_string="${1:-}"
  export -a args
  args=( $@ )
  source "$rvm_scripts_path"/$file
)
