#!/bin/bash
# usage:
#        trap_err_inject {file}
#        trap_err_eject {file}
#        trap_err_inject_dir {dir}
#        trap_err_eject_dir {dir}

function trap_err_colors_init(){
    color_green=$(echo -ne "\033[1;32m")
    color_red=$(echo -ne "\033[1;31m")
    color_yellow=$(echo -ne "\033[1;33m")
    color_reset=$(echo -ne "\033[0m")
}

function trap_err(){
    remote_caller=$(ps --no-headers --format cmd --pid ${PPID} | cut --delimiter ' ' --field 2 | sed "s/^-//")
    [ "${remote_caller}" = "/init" ] && return 0
    [ "${remote_caller}" = "" ] && return 0
    exit_code=$1
    local_caller_line=$2
    if [ "${local_caller_line}" = "[]" ] ; then
        local_caller_line="0"
        local_caller_print="$0"
    else
        local_caller_line=$(echo "${local_caller_line}" | tr -d '[]')
        local_caller_print=$(head -"${local_caller_line}" "$0" | tail -1 | sed 's/^ *//')
    fi
    local_line="${4:-0}"
    local_line_print="$(head -"${local_line}" "$0" | tail -1 | sed 's/^ *//')"
    trap_err_colors_init
    {
    echo "${color_red}******************************************${color_reset}"
    echo "${color_red}ERROR${color_reset}"
    echo "└─ ${remote_caller}"
    echo "   └─ $0"
    if [ "${local_caller_line}" -eq 0 ] ; then
       echo "      └─ line ${local_line}: ${local_line_print}"
       echo "         └─ exit code: ${exit_code}" 
    else
       echo "      └─ line ${local_caller_line}: ${local_caller_print}"
       echo "         └─ line ${local_line}: ${local_line_print}"
       echo "            └─ exit code: ${exit_code}"
    fi
    } >&2
}

function trap_err_check_file(){
    file=$1
    [ -z "$1" ] && trap_err_colors_init && echo "Usage: trap_check_file {sh file}" && return 1
    [ ! -f "${file}" ] && trap_err_colors_init && echo "${color_red}${file}${color_reset} does not exists" && return 1
    trap_count=$(grep -c "^trap" "${file}" || true)
    trap_err_colors_init
    [ "${trap_count}" -gt 0 ] && trap_count="${color_green}trap injected${color_reset}" || trap_count="${color_yellow}trap ejected${color_reset}"
    echo "file: ${file}: ${trap_count}"
}

trap_err_inject(){
    file=$1
    [ -z "${file}" ] && trap_err_colors_init && echo "${color_red}Usage:${color_reset} trap_err_inject {file}" && return 1
    [ "$(grep -c "^trap" "${file}" || true)" -eq 0 ] && sed -i "/\/bash$/a trap 'trap_err \$? [\$(caller)] \$LINENO' ERR" "${file}"
    trap_err_check_file "${file}"
}

trap_err_inject_dir(){
    dir=$1
    [ -z "${dir}" ] && trap_err_colors_init && echo "${color_red}Usage:${color_reset} trap_err_inject_dir {dir}" && return 1
    [ ! -d "${dir}" ] && trap_err_colors_init && echo "${color_red}${dir}${color_reset} does not exists" && return 1
    while read -r sh ; do
        trap_err_inject "${sh}"
    done < <(find . -type f -name "*.sh")
}

trap_err_eject(){
    file=$1
    [ -z "${file}" ] && echo "${color_red}Usage:${color_reset} trap_err_eject {file}" && return 1
    [ "$(grep -c "^trap" "${file}" || true)" -gt 0 ] && sed -i "/^trap/d" "${file}"
    trap_err_check_file "${file}"
}

trap_err_eject_dir(){
    dir=$1
    [ -z "${dir}" ] && trap_err_colors_init && echo "${color_red}Usage:${color_reset} trap_err_eject_dir {dir}" && return 1
    [ ! -d "${dir}" ] && trap_err_colors_init && echo "${color_red}${dir}${color_reset} does not exists" && return 1
    while read -r sh ; do
        trap_err_eject "${sh}"
    done < <(find . -type f -name "*.sh")
}

function main(){
    export -f trap_err_colors_init
    export -f trap_err
    export -f trap_err_check_file
    export -f trap_err_inject
    export -f trap_err_inject_dir
    export -f trap_err_eject
    export -f trap_err_eject_dir
}

main

