#!/bin/bash

# @author Sergey Bondarenko

readonly bash_needed_version=3
readonly bash_major_version=${BASH_VERSION%%[^0-9]*}

if [ "${bash_major_version}" -lt "${bash_needed_version}" ]; then
    status_message "Sorry, but bash version should be more or equal of ${bash_needed_version}!" error
fi

# Print message on the screen.
#
# @param string $1
#   Message which will be printed.
# @param string [$2=success]
#   Type of a message. Allowed values are: "error", "success", "warning"
#   and "normal". If "error" type was specified then script stop execution
#   immediately.
status_message()
{
    if [[ -n "${1}" ]]; then
        local status="success"
        local error=$(tput setaf 1)
        local normal=$(tput sgr0)
        local success=$(tput setaf 2)
        local warning=$(tput setaf 3)

        readonly error normal success warning

        if [ "${2}" ]; then
            status=${2}
        fi

        printf "%*s\r%s\n" "$(($(tput cols)+${#status}+2))" "${!status}[${status}]$(tput sgr0)" "${1}"

        if [ "${status}" == "error" ]; then
            exit
        fi
    fi
}

# User interaction. Valid response options: "y" or "Y" and "n" or "N". If
# a user gives a negative answer (n or N), then script execution will be
# stopped immediately, positive (y or Y) - scenario will do what the user
# has given a consent. In another cases (any other text) script will be
# wait one of the correct answers.
#
# @param string $1
#   An interrogative message.
ask()
{
    if [[ -n "${1}" ]]; then
        local answer;
        local message="${1} [y/n]: ";

        if ${y}; then
            echo "${message}y"
            return 0
        fi

        while true; do
            read -p "${1} [Y/n]: " answer
            case ${answer} in
                [Yy])
                    return 0
                ;;
                [Nn])
                    return 1
                ;;
                *)
            esac
        done
    fi
}

user_input()
{
    if [[ -n "${1}" ]]; then
        local answer;

        while true; do
            read -p "${1}: " answer
            if [ -z "${answer}" ]; then
                status_message "Type something." warning
            else
                echo ${answer}
                return 0
            fi
        done
    fi
}

dir_full_path()
{
    if [[ -d "${1}" ]]; then
        echo $(cd "$1" > /dev/null 2>&1 && pwd)
    fi
}

catch_last_error()
{
    if [ $? -gt 0 ]; then
        status_message "${1}" error
    fi
}

# Replace string in file.
#
# @param string $find
# @param string $replace
# @param string $file
replace_in_file()
{
    if [ "$#" -ge 3 ]; then
        if [ -f "${3}" ]; then
            sed "s|${1}|${2}|g" ${3} > ${3}.tmp
            mv ${3}.tmp ${3}
        else
            status_message "The `pwd`/$3 does not exist." error
        fi
    else
        status_message "Was passed $# arguments while expected 3." error
    fi
}

# Retrieve an absolute path of symlink (recursively).
#
# @param string $symlink
get_symlink_full_path()
{
    local link=${1}
    local cd=${link}

    while true; do
        if [ -L "${link}" ]; then
            cd=${link}
            link=`readlink ${link}`
        else
            for var in cd link; do
                if [ -f "${!var}" ]; then
                    declare "${var}"=${!var%/*}
                fi

                cd ${!var}
            done

            echo `pwd`
            break
        fi
    done
}

for i in ${@}; do
    # Remove leading dashes from a parameter declaration. After that,
    # string will have the following form: "name=value", and will be
    # splitted by "=" symbol.
    key_value=${i#--}

    if [ ${key_value} != ${i} ]; then
        arg=${key_value%=*}
        val=${key_value#*=}

        if [ ${arg} == ${val} ]; then
            declare "${arg}"=true
        else
            declare "${arg}"=${val}
        fi
    fi
done

# Directory with Bash files.
commands_path=${0}
command=${1}

package_dir=`get_symlink_full_path ${commands_path}`
commands_path=${package_dir}/commands

# Remove the "/scripts" from the end of executable file.
package_dir=${package_dir%/*}

# Allow to run commands defined as parameters.
for override in init; do
    if [ -n "${!override}" ]; then
        command=${override}
        break
    fi
done

if [ ! -d "${package_dir}" ]; then
    status_message "Cannot get the package directory." error
fi

# Execute the command if it has been defined.
if [ ! -f "${commands_path}/${command}" ]; then
    command="__init"
fi

. ${commands_path}/${command}
