#!/bin/bash

# This script is a wrapper for programs that may have alternate versions (e.g. python2, python3).  This
# wrapper allows the user to influence the selection of the program version by setting the <program
# name>_VERSION (e.g. PYTHON_VERSION, ROBOT_VERSION, etc.) environment variable.

# Users would be expected to create a link with the base name of the program that points to this file.

# Example:
# cd openbmc-test-automation/bin
# ln -s select_version python

# The PATH variable should contain the expanded path to openbmc-test-automation/bin.

# If <program name>_VERSION is blank or not set, then the program version will be whatever the system
# default program version is.  If <program name>_VERSION is set to a value, then that value will be appended
# to the name of the program (e.g. if PYTHON_VERSION = "3", then python3 will be used.).  If <program
# name>_VERSION is set to some value that does not correspond to a valid program version for the given
# system, this program will fail.


# Make sure program_name is set.
program_name="${0##*/}"
program_uppercase_name=${program_name^^}


function get_target_program_path() {
    local target_program_path_var="${1:-target_program_path}" ; shift

    # Get the full path to the "real" program and assign it to the variable named in target_program_path_var.

    # Description of argument(s):
    # target_program_path_var         The name of the variable to receive the result.

    # Example result:

    # /usr/bin/python3

    local version_var_name
    local alternate_program_name
    local base_program_path
    local base_program_name
    local candidate
    local candidates
    local base_file_path

    # The typical use of this program would be to create a link to it like this:
    # ln -s select_version python
    # That being the case, get the name of this actual program (rather than the name of the link to it).
    base_program_path=$(readlink -f "${0}")
    base_program_name=${base_program_path##*/}

    if [ "${program_name}" == "${base_program_name}" ] ; then
        {
            echo -n "**ERROR** ${base_program_name} should never be called directly."
            echo "  Only links to ${base_program_name} should be called."
        } >&2
        exit 1
    fi

    # Compose the version_var_name value (e.g. PYTHON_VERSION).
    version_var_name=${program_uppercase_name}_VERSION
    # Compose the alternate_program_name (e.g. python3).
    alternate_program_name=${program_name}${!version_var_name}

    # Now use the "type" built-in to search the PATH variable for a list of target program candidates.
    candidates=$(type -ap ${alternate_program_name})

    # Example candidates:
    # /home/robot/openbmc-test-automation/bin/python
    # /usr/bin/python

    # In this example, the first candidate is actually a link to
    # /home/robot/openbmc-test-automation/bin/select_version.  As such it will be rejected.

    for candidate in ${candidates}
    do
        if [ -L "${candidate}" ] ; then
            # The candidate is a link so we need to see if it's a link to this program file.
            base_file_path=$(readlink "${candidate}")
            [ "${base_file_path}" == "${base_program_name}" ] && continue
        fi

        # The candidate is NOT a link so it qualifies as the desired target program path.
        eval ${target_program_path_var}=\"\${candidate}\"
        return

    done

}


# Main

get_target_program_path target_program_path

# Compose program path var name (e.g. PYTHON_PGM_PATH).
pgm_path_var_name=${program_uppercase_name}_PGM_PATH
# Set and export pgm_path_var_name (e.g. PYTHON_PGM_PATH=/usr/bin/python3).  This value can be used by
# child programs for debug.
eval export ${pgm_path_var_name}=${target_program_path}

if [ "${1}" == "--print_only" ] ; then
    echo "${target_program_path}"
else
    # Use exec in order to replace this process with the target process.
    exec ${target_program_path} "${@}"
fi