#!/usr/bin/env bash

export escape_flag=1 _first=${__array_start} _second=$[__array_start + 1]

__rvm_md5_for()
{
  if command -v md5 > /dev/null; then
    echo "$1" | md5
  elif command -v md5sum > /dev/null ; then
    echo "$1" | md5sum | awk '{print $1}'
  else
    rvm_error "Neither md5 nor md5sum were found in the PATH"
    return 1
  fi

  return 0
}

__rvm_sha256_for()
{
  if command -v sha256sum > /dev/null ; then
    echo "$1" | sha256sum | awk '{print $1}'
  elif command -v sha256 > /dev/null ; then
    echo "$1" | sha256 | awk '{print $1}'
  elif command -v shasum > /dev/null ; then
    echo "$1" | shasum -a256 | awk '{print $1}'
  else
    rvm_error "Neither sha256sum nor shasum found in the PATH"
    return 1
  fi

  return 0
}

__rvm_md5_for_contents()
{
  if command -v md5 > /dev/null
  then
    echo "$1" | cat - "$1" | md5
  elif command -v md5sum > /dev/null
  then
    echo "$1" | cat - "$1" | md5sum | awk '{print $1}'
  else
    rvm_error "Neither md5 nor md5sum were found in the PATH"
    return 1
  fi

  return 0
}

__rvm_sha256_for_contents()
{
  if command -v sha256sum > /dev/null ; then
    echo "$1" | cat - "$1" | sha256sum | awk '{print $1}'
  elif command -v sha256 > /dev/null ; then
    echo "$1" | cat - "$1" | sha256 | awk '{print $1}'
  elif command -v shasum > /dev/null ; then
    echo "$1" | cat - "$1" | shasum -a256 | awk '{print $1}'
  else
    rvm_error "Neither sha256sum nor shasum found in the PATH"
    return 1
  fi

  return 0
}

__rvm_rvmrc_key()
{
  printf "$1" | tr '[#/.=]' _
  return $?
}

__rvm_reset_rvmrc_trust()
{
  "$rvm_scripts_path/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "delete" >/dev/null 2>&1
  return $?
}

__rvm_trust_rvmrc()
{
  __rvm_reset_rvmrc_trust "$1"
  "$rvm_scripts_path/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "1;$(__rvm_md5_for_contents "$1")$(__rvm_sha256_for_contents "$1")" >/dev/null 2>&1
  return $?
}

__rvm_untrust_rvmrc()
{
  __rvm_reset_rvmrc_trust "$1"
  "${rvm_scripts_path:-"$rvm_path/scripts"}/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "0;$(__rvm_md5_for_contents "$1")$(__rvm_sha256_for_contents "$1")" >/dev/null 2>&1
  return $?
}

__rvm_rvmrc_stored_trust()
{
  "${rvm_scripts_path:-"$rvm_path/scripts"}/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")"
  return $?
}

__rvm_rvmrc_tools()
{
  export escape_flag=1

  local rvmrc_action="$1"

  if (( $# ))
  then
    shift
  fi

  local rvmrc_path="$(builtin cd "${1:-$PWD}" >/dev/null 2>&1; pwd)/.rvmrc"

  case "$rvmrc_action" in

    reset)

      __rvm_reset_rvmrc_trust "$rvmrc_path"
      echo "Reset trust for $rvmrc_path"
    ;;

    trust)

      __rvm_trust_rvmrc "$rvmrc_path"
      echo "Marked $rvmrc_path as trusted"
    ;;

    untrust)

      __rvm_untrust_rvmrc "$rvmrc_path"
      echo "Marked $rvmrc_path as untrusted"

    ;;

    trusted)

      if [[ -f "$rvmrc_path" ]]
      then
        local saveIFS=$IFS
        IFS=$';'
        local trust=($(__rvm_rvmrc_stored_trust "$rvmrc_path"))
        IFS=$saveIFS

        if [[ "${trust[${_second}]:-'#'}" != "$(__rvm_md5_for_contents "$1")$(__rvm_sha256_for_contents "$1")" ]]
        then
          echo "The rvmrc at '$rvmrc_path' contains unreviewed changes."

        elif [[ "${trust[${_first}]}" == '1' ]]
        then
          echo "The rvmrc at '$rvmrc_path' is currently trusted."

        elif [[ "${trust[${_first}]}" == '0' ]]
        then
          echo "The rvmrc at '$rvmrc_path' is currently untrusted."

        else
          echo "The trustiworthiness of '$rvmrc_path' is currently unknown."
        fi
      else
        echo "There is no $rvmrc_path"
      fi
    ;;

    is_trusted)

      if [[ -f "$rvmrc_path" ]]
      then
        local saveIFS=$IFS
        IFS=$';'
        local trust=($(__rvm_rvmrc_stored_trust "$rvmrc_path"))
        IFS=$saveIFS

        if [[ "${trust[${_second}]:-'#'}" != "$(__rvm_md5_for_contents "$rvmrc_path")$(__rvm_sha256_for_contents "$rvmrc_path")" ]]
        then
          return 1
        elif [[ "${trust[${_first}]}" == '1' ]]
        then
          return 0
        else
          return 1
        fi
      else
        return 1
      fi
    ;;

    load)

      rvm_rvmrc_cwd="" rvm_trust_rvmrcs_flag=1  \
        __rvm_project_rvmrc "$(dirname "$rvmrc_path")"
    ;;

    try_to_read_ruby)
      if ! __rvm_rvmrc_tools is_trusted $(dirname "$rvmrc_path")
      then
        # subprocess to not mess with current process variables
        ( __rvm_project_rvmrc "$(dirname "$rvmrc_path")" )
      fi

      if __rvm_rvmrc_tools is_trusted $(dirname "$rvmrc_path")
      then
        rvm_action="${rvm_action:-use}"
        rvm_ruby_string="$(
          __rvm_rvmrc_tools load $(dirname "$rvmrc_path")
          __rvm_env_string
        )"
        rvm_ruby_strings="$rvm_ruby_string"
      else
        rvm_action="error"
        rvm_error_message="The give path does not contain .rvmrc (or it is not trusted): '$(dirname "$rvmrc_path")' rest of params: '$@'"
      fi
      ;;

    *)
      echo "Usage: rvm rvmrc {trust,untrust,trusted,load,reset,is_trusted,try_to_read_ruby}"
      return 1
    ;;
  esac

  unset escape_flag

  return $?
}

__rvm_check_rvmrc_trustworthiness()
{
  # Trust when they have the flag... of doom!
  if [[ -n "$1" && ${rvm_trust_rvmrcs_flag:-0} == 0 ]]
  then
    local saveIFS="$IFS" trust
    IFS=$';'
    trust=( $( __rvm_rvmrc_stored_trust "$1" ) )
    IFS="$saveIFS"

    if [[ "${trust[${_second}]:-'#'}" != "$(__rvm_md5_for_contents "$1")$(__rvm_sha256_for_contents "$1")" ]]
    then
      __rvm_ask_to_trust "$1"
    else
      [[ "${trust[${_first}]}" == '1' ]]
    fi

  fi
  local result=$?
  unset escape_flag
  return $result
}

__rvm_display_rvmrc()
{
  printf "
==============================================================================
= The contents of the .rvmrc file will now be displayed.                     =
= After reading the file, you will be prompted again for 'yes or no' to set  =
= the trust level for this particular version of the file.                   =
=                                                                            =
= Note: You will be re-prompted each time the .rvmrc file's contents change  =
= changes, and may change the trust setting manually at any time.            =
==============================================================================
(( press a key to review the .rvmrc file ))\n\n"

read -r anykey

command cat -v "${_rvmrc}"

  printf "
==============================================================================
= Viewing of %s complete.
==============================================================================
= Trusting an .rvmrc file means that whenever you cd into this directory,    =
= RVM will run this .rvmrc shell script.                                     =
= Note that if the contents of the file change, you will be re-prompted to   =
= review the file and adjust its trust settings. You may also change the     =
= trust settingsmanually at any time with the 'rvm rvmrc' command.           =
==============================================================================
\n" "${_rvmrc}"
}

__rvm_ask_to_trust()
{
  local trusted value anykey _rvmrc="${1}"

  if [[ ! -t 0 ]] || (( ${rvm_promptless:=0} == 1 ))
  then
    return 2
  fi

  printf "==============================================================================
= NOTICE                                                                     =
==============================================================================
= RVM has encountered a new or modified .rvmrc file in the current directory =
= This is a shell script and therefore may contain any shell commands.       =
=                                                                            =
= Examine the contents of this file carefully to be sure the contents are    =
= safe before trusting it! ( Choose v[iew] below to view the contents )      =
==============================================================================
"
  trusted=0
  while (( ! trusted ))
  do
    printf "Do you wish to trust this .rvmrc file? (%s)\n" "${_rvmrc}"
    printf "%s" 'y[es], n[o], v[iew], c[ancel]> '

    read response

    value="$(echo -n "${response}" | tr '[[:upper:]]' '[[:lower:]]' | __rvm_strip)"

    case "${value:-n}" in
      v|view)
        __rvm_display_rvmrc
        ;;
      y|yes)
        trusted=1
      ;;
      n|no)
        break
      ;;
      c|cancel)
        return 0
      ;;
    esac
  done

  if (( trusted ))
  then
    __rvm_trust_rvmrc "$1"
    return 0
  else
    __rvm_untrust_rvmrc "$1"
    return 1
  fi
}

# Checks the rvmrc for the given directory. Note that if
# argument is passed, it will be used instead of pwd.
__rvm_project_rvmrc()
{
  local working_dir

  # Get the first argument or the pwd.
  working_dir="${1:-"$PWD"}"

  while : ; do

    if [[ -z "$working_dir" || "$HOME" == "$working_dir" || "/" == "$working_dir" ]]
    then
      if [[ -n "${rvm_current_rvmrc:-""}" ]]
      then
        __rvm_remove_rvm_from_path ; __rvm_conditionally_add_bin_path
        if (( ${rvm_project_rvmrc_default:-0} == 1 ))
        then
          __rvm_load_environment "default"
        elif [[ -n "${rvm_previous_environment:-""}" ]]
        then
          __rvm_load_environment "$rvm_previous_environment"
        fi
        unset rvm_current_rvmrc rvm_previous_environment
      fi
      break
    else
      if [[ -f "$working_dir/.rvmrc" ]]
      then
        if [[ "${rvm_current_rvmrc:-""}" != "$working_dir/.rvmrc" ]]
        then
          __rvm_check_rvmrc_trustworthiness "$working_dir/.rvmrc"
          local rvm_trustworthiness_result=$?
          if  (( $rvm_trustworthiness_result == 0 ))
          then
            __rvm_remove_rvm_from_path ; __rvm_conditionally_add_bin_path
            rvm_previous_environment="$(__rvm_env_string)"
            rvm_current_rvmrc="$working_dir/.rvmrc"
            source "$working_dir/.rvmrc"
            return 0
          else
            return "$rvm_trustworthiness_result"
          fi
        fi
        break
      else
        working_dir="$(dirname "$working_dir")"
      fi
    fi
  done
  return $?
}

__rvm_project_rvmrc_with_env()
{
  if [[ -n "${rvm_scripts_path:-}" || -n "${rvm_path:-}" ]]
  then
    # Load env - setup all required variables, __rvm_teardown is called on the end
    __rvm_cleanse_variables
    __rvm_load_rvmrc
    __rvm_setup
    source "${rvm_scripts_path:-"$rvm_path/scripts"}/initialize"
  fi

  __rvm_project_rvmrc "$@"
  local result=$?

  if [[ -n "${rvm_scripts_path:-}" || -n "${rvm_path:-}" ]]
  then
    # Clean env mess
    __rvm_teardown
  fi

  return ${result:-0}
}

__rvm_set_rvmrc()
{
  local flags
  true ${rvm_verbose_flag:=0}

  if [[ "$HOME" != "$PWD" ]]
  then
    if (( rvm_verbose_flag ))
    then
      flags="use "
    fi

    if [[ -s .rvmrc ]]
    then
      mv .rvmrc .rvmrc.$(date +%m.%d.%Y-%H:%M:%S)
      rvm_warn ".rvmrc is not empty, moving aside to preserve."
    fi

    local identifier=$(__rvm_env_string)

    printf "#!/usr/bin/env bash

# This is an RVM Project .rvmrc file, used to automatically load the ruby
# development environment upon cd'ing into the directory

# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
environment_id=\"$identifier\"

#
# Uncomment following line if you want options to be set only for given project.
#
# PROJECT_JRUBY_OPTS=( --1.9 )

#
# First we attempt to load the desired environment directly from the environment
# file. This is very fast and efficient compared to running through the entire
# CLI and selector. If you want feedback on which environment was used then
# insert the word 'use' after --create as this triggers verbose mode.
#
if [[ -d \"\${rvm_path:-\$HOME/.rvm}/environments\" \\
  && -s \"\${rvm_path:-\$HOME/.rvm}/environments/\$environment_id\" ]]
then
  \\. \"\${rvm_path:-\$HOME/.rvm}/environments/\$environment_id\"

  if [[ -s \"\${rvm_path:-\$HOME/.rvm}/hooks/after_use\" ]]
  then
    . \"\${rvm_path:-\$HOME/.rvm}/hooks/after_use\"
  fi
else
  # If the environment file has not yet been created, use the RVM CLI to select.
  if ! rvm --create $flags \"\$environment_id\"
  then
    echo \"Failed to create RVM environment '\${environment_id}'.\"
    exit 1
  fi
fi

#
# If you use an RVM gemset file to install a list of gems (*.gems), you can have
# it be automatically loaded. Uncomment the following and adjust the filename if
# necessary.
#
# filename=\".gems\"
# if [[ -s \"\$filename\" ]]
# then
#   rvm gemset import \"\$filename\" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
# fi

# If you use bundler, this might be useful to you:
# if command -v bundle && [[ -s Gemfile ]]
# then
#   bundle install
# fi


" >> .rvmrc

  else
    rvm_error ".rvmrc cannot be set in your home directory.\
      \nThe home .rvmrc is for global rvm settings only."
  fi
}
