# Copyright 2012 Roy Liu
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# Contains functionality common to plugin scripts.

# Inspects the gemspec manifests generated by the `rehash.rb` script to see if there's a suitable gem executable for
# the given command.
function find_bundled_executable {
    local -- manifest_dir=$1
    local -- manifest_entries

    if [[ -f "${manifest_dir}/manifest.txt" ]]; then
        manifest_entries=$(cat -- "${manifest_dir}/manifest.txt")
    else
        manifest_entries=()
    fi

    ifs_save=$IFS

    IFS=$'\n'
    manifest_entries=($manifest_entries)
    IFS=$ifs_save

    local -- project_dir
    local -- gemspec_entries

    for (( i = 0; i < ${#manifest_entries[@]}; i += 2 )); do
        project_dir=$(dirname -- "${manifest_entries[$i]}")

        if [[ "$project_dir" != "/" ]]; then
            project_dir="${project_dir}/"
        fi

        current_dir=$PWD

        if [[ "$current_dir" != "/" ]]; then
            current_dir="${current_dir}/"
        fi

        # Check if the manifest directory is a prefix of the current directory.
        if [[ "$current_dir" == "${current_dir##$project_dir}" ]]; then
            continue
        fi

        gemspec_entries=$(cat -- "${manifest_dir}/${manifest_entries[$(($i + 1))]}")

        ifs_save=$IFS

        IFS=$'\n'
        gemspec_entries=($gemspec_entries)
        IFS=$ifs_save

        for (( j = 0; j < ${#gemspec_entries[@]}; j += 2 )); do
            if [[ "${gemspec_entries[$j]}" != "$RBENV_COMMAND" ]]; then
                continue
            fi

            echo "${gemspec_entries[$(($j + 1))]}/${gemspec_entries[$j]}"

            return -- 0
        done
    done

    return -- 1
}

# Gets whether the heavyweight, script-based rehash operation is needed by comparing the modification times of Gemfile
# manifests against their Gemfiles.
function needs_rehash_script {
    local -- manifest_dir=$1

    if [[ ! -f "${manifest_dir}/manifest.txt" ]]; then
        return -- 0
    fi

    local -- acc=$PWD

    while [[ "$acc" != "$(dirname -- "$acc")" ]]; do
        if [[ -f "${acc}/Gemfile" ]]; then
            return -- 0
        fi

        acc=$(dirname -- "$acc")
    done

    local -- manifest_entries=$(cat -- "${manifest_dir}/manifest.txt")
    local -- ifs_save=$IFS

    IFS=$'\n'
    manifest_entries=($manifest_entries)
    IFS=$ifs_save

    for (( i = 0; i < ${#manifest_entries[@]}; i += 2 )); do
        if [[ "${manifest_dir}/${manifest_entries[$(($i + 1))]}" -ot "${manifest_entries[$i]}" ]]; then
            return -- 0
        fi
    done

    return -- 1
}

# Generates shims for the executables listed in Gemfile manifests.
function make_gemfile_shims {
    local -- manifest_dir=$1

    if [[ ! -f "${manifest_dir}/manifest.txt" ]]; then
        return -- 0
    fi

    local -- manifest_entries=$(cat -- "${manifest_dir}/manifest.txt")

    ifs_save=$IFS

    IFS=$'\n'
    manifest_entries=($manifest_entries)
    IFS=$ifs_save

    for (( i = 0; i < ${#manifest_entries[@]}; i += 2 )); do
        gemspec_entries=$(cat -- "${manifest_dir}/${manifest_entries[$(($i + 1))]}")

        ifs_save=$IFS

        IFS=$'\n'
        gemspec_entries=($gemspec_entries)
        IFS=$ifs_save

        for (( j = 0; j < ${#gemspec_entries[@]}; j += 2 )); do
            gem_executable="${gemspec_entries[$(($j + 1))]}/${gemspec_entries[$j]}"

            if [[ ! -f "$gem_executable" ]]; then
                continue
            fi

            cd -- "$SHIM_PATH" && make_shims "$gem_executable"; cd -- "$PWD"
        done
    done

    return -- 0
}

# Computes MD5 hashes in a cross-platform way.
function md5 {
    case "$(uname)" in
        Linux)
            local -- result=$(echo "$1" | md5sum)
            echo "${result:0:32}"
            return -- $?
            ;;

        Darwin|FreeBSD|NetBSD)
            echo "$1" | command -- md5
            return -- $?
            ;;

        *)
            echo "Unsupported operating system" >&2
            return -- 127
            ;;
    esac
}

# The plugin's root directory.
plugin_root_dir=$(dirname -- "$(dirname -- "$(dirname -- "$(dirname -- "${BASH_SOURCE[0]}")")")")

# Whether the plugin is disabled.
if [[ -f "${plugin_root_dir}/share/rbenv/bundler/enabled_$(md5 "$RBENV_ROOT")" ]]; then
    plugin_enabled="1"
else
    plugin_enabled=""
fi
