#!/bin/bash

debug.version()              # prints out the hard coded version tag of $This 
{
 debug.log "$0 debug GitHub version: 20210716 12:51"
}



function step()
{
  if [ "$STEP_DEBUG" = "ON" ]; then
    set +x
    echo -e "\033[37m+<-----------------------------------------"
    echo "> function ${FUNCNAME[1]}(" "${BASH_ARGV[@]}" ")  in file: ${BASH_SOURCE[1]}"
    echo -e "> line: ${BASH_LINENO[1]} '${BASH_COMMAND}'\033[0m"

    read -p '' CONT

    if [[ ! "$CONT" = "" ]]; then
      case $CONT in
        h)
            echo "
            h     this help
            e     expands variable in the command
            n     next command full with debug
            ENTER next command

            d     toggle debug messages
            t     trace the stack
            s     continue silently
            c     with debug
            p     print PATH
            ll    list dir
            cd    changing to entered path
            root  tree /root
            home  tree /home
            i     check eamd
            eamd  tree workspace

            cmd   runn command (BE CAREFULL)

            q     exit
                all other commands exit too
            "
            step
            ;;
        s)
            removeTrap
            DEBUG=OFF
            debug.log "DEBUG is OFF"
            set +x
            ;;
        n)
            #removeTrap
            DEBUG=ON
            set -x
            ;;
        x)
            DEBUG=ON
            removeTrap
            set -x
            ;;
        c)
            DEBUG=ON
            removeTrap
            set +x
            ;;
        e)
            echo "> expands to: $(eval echo "$BASH_COMMAND")"
            step
            ;;
        r)
            export STEP_TILL_NEXT_RETURN=ON
            removeTrap
            warn.log "continue till next Return"
            step
            ;;
        t)
            stackTrace
            ;;
        ls)
            ls -al
            step 
            ;;
        d)
            toggleDebug
            step
            ;;
        p)
            console.log "PATH=$PATH"
            step
            ;;
        ll)
            pwd
            ls -alF
            step
            ;;
        root)
            tree -aL 2 /root
            step
            ;;
        home)
            tree -aL 2 /home
            step
            ;;
        eamd)
            tree -aL 2 /$defaultWorkspace/..
            step
            ;;
        i)
            eamd check
            step
            ;;
        cd)
            read -p 'cd to?   >' CD_DIR
            cd $CD_DIR
            step
            ;;
        cmd)
            read -p 'command?  BE CAREFULL >' command
            set -x
            $command
            step
            ;;    
        env)
            read -p 'ENV VARIBALE NAME>' env
            set -x
            echo -e "\033[1;33mexport $env=${!env}\033[0m"
            step
            ;;          
        *)
            set +x
            warn.log "FORCE EXIT because of command: $CONT"
            exit 0
      esac
    #else
      #echo "ENTER: continue"
    fi
  #else
    #echo "Step Debug is $STEP_DEBUG"
  fi
}

function stackTrace() {
            i=0;
            #for (( i=0; i<=${#BASH_LINENO[@]}; i++)); do
            echo -e "\033[1;37m" 
            for l in ${BASH_LINENO[@]}; do
                printf "i: %2d  line: %6d  function: %-20s  file: %-30s   args: " "$i" "$l" "${FUNCNAME[$i]}()" "${BASH_SOURCE[$i]}"
                echo "\"${BASH_ARGV[@]}\" and \"$@\""
                ((i++))
            done
            echo -e "\033[0m"
            step
}

function stepDebugger() {

  if [ "$1" = "OFF" ]; then
      removeTrap
  fi
  if [ "$1" = "ON" ]; then
      export STEP_DEBUG=ON
  fi

}

function setTrap() {
  debug.log "trap DEBUG set to step"
  #export PS4='\033[37m+${LINENO}: \033[0m'
  #export PS4='\033[90m+${LINENO}: '

  trap step DEBUG
  #set -e
  trap 'onError ${?}' ERR
  trap 'onReturn ${?}' RETURN
  trap 'onExit  ${?}' EXIT 
}

function checkTrace() {
    case $- in
        *x* ) 
            echo "Trace is ON"
            export TRACE=ON
            ;;
        * )               
            echo "Trace is OFF"
            export TRACE=OFF;
            ;;
    esac
}

function setTrace() {
    case $TRACE in
        ON ) 
            set -x
            export TRACE=ON
            ;;
        * )               
            set +x
            export TRACE=OFF
            ;;
    esac
}


function removeTrap() {
  export STEP_DEBUG=OFF
  #trap - DEBUG ERR RETURN EXIT
}

function checkDebug() {

  if [[ "$(basename -- "$0")" == "debug" ]]; then
    # called
    if [ -n "$1" ]; then
        DEBUG=$1
    fi
    warn.log "debug has no effect if it was not sourced with . debug"
  else
    # sourced
    debug.log "debug was sourced from: $0"
    if [[ "$(basename -- "$0")" == "-bash" ]]; then
       debug.log "sourced from: bash"
       DEBUG=$1
    fi
  fi


  if [ -n "$DEBUG" ]; then
    echo "DEBUG was $DEBUG, and is now ON"
    case $DEBUG in
      X)
        set -x
        ;;
      OFF)
        unset DBEUG
        ;;
      *)
        export DEBUG=ON
    esac
  else
    debug.log "DEBUG is $DEBUG"
  fi
}

function toggleDebug() {
    if [ "ON" = "$DEBUG" ]; then 
        DEBUG=OFF
        #set +x
    else
        DEBUG=ON
    fi
    warn.log "Toggeld DEBUG to $DEBUG"
}

function onReturn() {
    debug.log "function ${FUNCNAME[1]} returned with code: $1 and RETURN=$2"
    if [ "$0" = "$2" ]; then
        #do not stop when in this $0 debug file $2
        return 0
    fi
    
    if [ "ON" = "$STEP_TILL_NEXT_RETURN" ]; then 
        STEP_TILL_NEXT_RETURN=OFF
        export STEP_DEBUG=ON
        #set +x
    fi
#   if [ -z "$2" ]; then
#     RETURN=$2
#   fi
}

function onError() {
  #echo -e "\033[1;31m   line: ${BASH_LINENO[2]} '${BASH_COMMAND[2]}'\033[0m"
    if [ "$1" = "1" ]; then
      return
    fi
    
    error.log         "function ${FUNCNAME[1]} in line: ${BASH_LINENO[1]} returned with ERROR code: $1"
    if [ "ON" = "$DEBUG" ]; then
      export STEP_DEBUG=
      stackTrace
      export STEP_DEBUG=ON
    fi
}

function onExit() {
  debug.log "exiting"
}

debug.log() {
    if [ "ON" = "$DEBUG" ]; then
        #test -t 1 && tput setf 7     
        echo -e "\033[1;36m- $@\033[0m"
        #echo "- $@"
        #test -t 1 && tput sgr0 # Reset terminal
    fi
}

console.log() {
    #test -t 1 && tput bold; tput setf 7                                            ## white bold
    echo -e "\033[0m>  $@"
    #test -t 1 && tput sgr0 # Reset terminal
}
error.log() {
    err.log "$@"
}
err.log() {
    #test -t 1 && tput bold; tput setf 4  
    #echo "ERROR>  $@"
    echo -e "\033[1;31mERROR> $@\033[0m"    
    #test -t 1 && tput sgr0 # Reset terminal
    if [ "ON" = "$DEBUG" ]; then 
        export STEP_DEBUG=ON
    fi   
}
warn.log() {
    #test -t 1 && tput bold; tput setf 6
    echo -e "\033[1;33m> WARNING $@\033[0m"                                    ## yellow
    #test -t 1 && tput sgr0 # Reset terminal
}
stop.log() {
    if [ "ON" = "$DEBUG" ]; then 
        #test -t 1 && tput bold; tput setf 6                                    ## green
        #echo "BREAKPOINT> $@"
        echo -e "\033[1;32mBREAKPOINT> $@\033[0m" 
        #test -t 1 && tput sgr0 # Reset terminal
        export STEP_DEBUG=ON
    fi  
}
success.log() {
    if [ "ON" = "$DEBUG" ]; then 
        echo -e "\033[1;32mSUCCESS> $@\033[0m" 
    fi  
}

checkDebug "$@"

debug.version
setTrap
