#!/bin/bash
# shellcheck disable=SC1090
# Various Build utils ##############################################################################################

export RED='\033[0;31m'
export GREEN='\033[0;32m'
export YELLOW='\033[1;33m'
export WHITE='\033[1;37m'
export NC='\033[0m'
export CYAN='\033[38;5;36m'

# retrieve the number of executing processors
export NCPU="$(getconf _NPROCESSORS_ONLN 2> /dev/null)"

# Prints call stack of function, script path and line where function was called
function get_stack()
{
    echo "Stack trace:"
    # to avoid noise we start with 1 to skip get_stack caller
    local i
    local stack_size=${#FUNCNAME[@]}
    for (( i=1; i<"$stack_size" ; i++ )); do
        local func="${FUNCNAME[$i]}"
        [ x"$func" = x ] && func=MAIN
        local linen="${BASH_LINENO[(( i - 1 ))]}"
        local src="${BASH_SOURCE[$i]}"
        [ x"$src" = x ] && src=non_file_source
        printf "\tFunction: %-20s    File: %s    Line: %s\n" "$func" "$src" "$linen"
    done
}

# Prints text with CYAN marker: [INFO] <text>
function print_info()
{
    [ -t 1 ] && echo -e "${CYAN}[INFO]${NC}" "$@"
    [ -t 1 ] || echo -e "[INFO]" "$@"
}

# Prints text with CYAN marker: <text>
function printCyan() {
    echo -e "\e[1;36m$1\e[m"
}

# Prints text with RED marker: [ERROR] <text>
function print_error()
{
    [ -t 1 ] && echo -e "${RED}[ERROR]${NC}" "$@" >&2
    [ -t 1 ] || echo -e "[ERROR]" "$@" >&2
    get_stack
    return 1
}

# Prints text with RED marker: <text>
function printRed() {
    echo -e "\e[1;31m$1\e[m"
}

# Prints text with GREEN marker: [SUCCESS] <text>
function print_success()
{
    [ -t 1 ] && echo -e "${GREEN}[SUCCESS]${NC}" "$@"
    [ -t 1 ] || echo -e "[SUCCESS]" "$@"
}

# Prints text with GREEN marker: <text>
function printGreen() {
    echo -e "\e[1;32m$1\e[m"
}

# Prints text with YELLOW marker: [WARNING] <text>
function print_warning()
{
    echo -e "${YELLOW}[WARNING]${NC}" "$@"
}

# Prints text with YELLOW marker: <text>
function printYellow() {
    echo -e "\e[1;33m$1\e[m"
}

# If 0 - Prints [SUCCESS] label with specified message.
# If !0 - Prints [ERROR] label with specified message.
# Parameters:
#       $1 - return code of operation to check.
#       $2 - Message to print.

# Usage: use $? as $q parameter right after operation that you want to check.
# Use second argument as message to print description.
# Example:
#            ../<some_folder>/some_script.sh <with_some_parameters>
#            check_return_code $? "Some script with some parameters experienced some errors."
#
function check_return_code()
{
    if [ "$1" != "0" ]
    then
        print_error "Code: $1. $2"
        exit "$1"
    else
        print_success "Code: $1. $2"
    fi
}

function contain_element()
{
    local e

    for e in "${@:2}";
    do
        [[ "$e" == "$1" ]] && return 0
    done

    return 1
}

# Pass arguments as strings: check_required "Error message" "$PARAM_TO_CHECK"
function check_required()
{
    if [ "$2" == "" ]; then
        print_error "Message: $1"
        exit 1
    fi
}

function check_existing()
{
    check_arg_num $# 2 "function check_existing()"

    if [ ! -e "$2" ]; then
        print_error "Message: $1 Not existing!"
        exit 1
    fi
}

# Source files
# $1 file to source
# $2 alternative file to source
# source $1 if $1 != "". Otherwise - source $2
# if $1 not "" and not exist on disc, return 1. Otherwise - return 0;
# exit with code 1, if $1 != "" and no defaults exist
function source_file()
{
    check_arg_num $# 2 "function source_file()"

    if [ "$1" != "" ]; then
        if [ -e "$1" ]; then
            print_info "Source: $1"
            source "${1}"
        else
            print_warning "Can not source file: $1"
            return 1
        fi
    else
        if [ -e "$2" ]; then
            print_info "Source default: $2"
            source "${2}"
        else
            print_error "Bad usage. Default file not exist: $2"
            exit 2
        fi
    fi

    return 0
}

# Usage: check_arg_num $# 3 "Expected min 3 arguments in <somewhere>"
function check_arg_num()
{
    if [ "$#" -ne 3 ]; then
        print_error "Bad usage of check_arg_num: $# args, but 3 expected."
        exit 1
    fi

    if [ "$1" -lt "$2" ]; then
        print_error "Illegal number of arguments. Message: $3"   
        exit 1
    fi
}

function get_right_library_name
{
    if [ "$TZ_PROVIDER" == "LINUX" ]; then
         local LIBRARY_EXT="so"
    else
        local LIBRARY_EXT="a"
    fi

    if [ "$TZ_PROVIDER" == "MOBICORE" ] && [ "$MC_DRIVER" == "TRUE" ]; then
        TZ_ENTITY="_dr"
    else
        TZ_ENTITY=""
    fi

    local LIBRARY_PATH_WITH_RIGHT_NAME=${TZ_PROVIDER,,}${TZ_ENTITY}_${CHIPSET,,}_scrypto_x${MACHINE}_${MODE,,}.${LIBRARY_EXT}
    basename "$LIBRARY_PATH_WITH_RIGHT_NAME"
}

function prepare_toolchains()
{
    if [ "$(echo "$ARM_RVCT_PATH" | grep '/opt/toolchains/ARM-DS5/6')" != "" ] ; then
        # If DS-5 V6 compiler is used
        rm -rf build_links
        mkdir -p build_links/bin

        ln -sf "${ARM_RVCT_PATH}"/bin/* "$(pwd)/build_links/bin/"
        export PATH=$PATH:${ARM_RVCT_PATH}/bin
        ln -sf "${TOOLS_DIR}"/build_env/* "$(pwd)/build_links/bin/"
        export ARM_RVCT_PATH_BIN=""
        ARM_RVCT_PATH_BIN=$(pwd)/build_links/bin/

        print_info "ARM_RVCT_PATH_BIN=$ARM_RVCT_PATH_BIN"
    fi
}

function is_library_with_asm()
{
    [ -e "$1" ] || print_error "The \"$1\" file doesn't exit!"
    return $(ar -t "$1" | grep -qe ".*S\.o$")
}

function runcmd {
    "$@"
    if [ $? -ne 0 ]; then
        print_error "$@"
    else
        print_success "$@"
    fi
    return $?
}

# Export functions
export -f get_stack
export -f print_info
export -f print_error
export -f print_success
export -f check_return_code
export -f contain_element
export -f check_required
export -f check_existing
export -f source_file
export -f check_arg_num
export -f get_right_library_name
export -f prepare_toolchains
export -f is_library_with_asm
export -f runcmd