#!/usr/bin/env bash

# echo "entering: ${BASH_SOURCE[0]}"
# echo "remove all echos to preseve output"
# echo ""

# export PS4='\e[90m+${LINENO} in ${#BASH_SOURCE[@]}>${FUNCNAME[0]}:${BASH_SOURCE[@]##*/} \e[0m'
#set -x 
#LOG_LEVEL=6

debug.v() {
  info.log "${BASH_SOURCE[@]##*/} version 2021-10-19 15:25"
}

if ! [ "$(type -t info.log)" = "function" ]; then
  source this; 
fi  
if ! [ "$(type -t log.init)" = "function" ]; then
  source $(dirname ${BASH_SOURCE[0]})/log; 
fi  


function step()
{

#  { 
#      set +x
#  } 2>/dev/null

    #info.log "step on level $LOG_LEVEL"
    if [ -z "$LOG_LEVEL" ]; then
        LOG_LEVEL=5
        export PS4='\e[90m  ${BASH_SOURCE[0]##*/} -> ${BASH_SOURCE[1]##*/}: ${FUNCNAME[0]}:${LINENO}   - ${BASH_SOURCE[@]##*/} \e[0m'
    fi

  if [ "$STEP_DEBUG" = "ON" ]; then

    echo -e "\e[37m+<----------------------------------------- $STEP_DEBUG" >/dev/stderr
    echo "> function ${FUNCNAME[1]}(" "${BASH_ARGV[@]}" ")  in file: ${BASH_SOURCE[1]}" >/dev/stderr
    echo -e "> line: ${BASH_LINENO[0]} '${BASH_COMMAND}'\e[0m" >/dev/stderr

    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     eneble debug messages
            x     TRON: full code trace on
            t     trace the stack
            s     continue silently
            c     continue
            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
            " >/dev/stderr
            step
            ;;
        s)
            check.debug.level 1
            ;;
        n)
            check.debug.level 6
            echo "ENTER: continue" >/dev/stderr
            export STEP_DEBUG=ON
            return 0
            ;;
        x)
            check.debug.level 6
            ;;
        c)
            log.level reset
            ;;
        e)
            echo "> expands to: $(eval echo "$BASH_COMMAND")" >/dev/stderr
            step
            ;;
        r)
            export STEP_TILL_NEXT_RETURN=ON
            removeTrap
            warn.log "continue till next Return"
            step
            ;;
        t)
            stackTrace
            ;;
        ls)
            ls -al
            step 
            ;;
        d)
            check.debug.level 5
            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 "\e[1;33mexport $env=${!env}\e[0m" >/dev/stderr
            step
            ;;          
        *)
            warn.log "FORCE EXIT because of command: $CONT" >/dev/stderr
            exit 0
      esac
    else
      echo "ENTER: continue" >/dev/stderr
      export STEP_DEBUG=ON
      return 0
    fi
  #else
    #echo "Step Debug is $STEP_DEBUG"
  fi
 
  check.debug.level
  if [ "$LOG_LEVEL" -gt "5" ]; then
      set -x
  fi
  #set -x # force debug
}

function stackTrace() {

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

function toggleDebug() {
    if [ "$LOG_LEVEL" -gt "4" ]; then
      check.debug.level 3
      export STEP_DEBUG=OFF
    else
      check.debug.level 5
      export STEP_DEBUG=OFF
    fi
    warn.log "Toggeld DEBUG to $DEBUG"
}

function noop() {
    return 0
}

function onReturn() {
    local logger=noop
    if [ "$(type -t debug.log)" = "function" ]; then
        logger=debug.log
        if [ $LOG_LEVEL -eq 5 ]; then
          logger=silent.log
        fi
    fi
    if [ "${FUNCNAME[1]}" = "result" ]; then
      logger=noop
    fi
    $logger "function ${FUNCNAME[1]} returned with code: $1 and $2 RESULT=$RESULT"
    if [ "${BASH_SOURCE[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
    #current.context
#   if [ -z "$2" ]; then
#     RETURN=$2
#   fi
} 2>/dev/null

function onError() {
  #echo -e "\e[1;31m   line: ${BASH_LINENO[2]} '${BASH_COMMAND[2]}'\e[0m"

  if [ -n "$1" ]; then
    RETURN_VALUE=$1
  fi

  # Suppress exit code 1 — normal control flow ([ ] tests, grep no-match, etc.)
  if [ "$RETURN_VALUE" = "1" ]; then
    return 0
  fi

  if [ -n "$RETURN_VALUE" ] && [ "$RETURN_VALUE" = "$EXPECTED_RETURN_VALUE" ]; then

    if [ -n "$ERROR_CODE_RECONFIG" ] && [ "$RETURN_VALUE" -eq "$ERROR_CODE_RECONFIG" ] 2>/dev/null; then
      unset STARTED_OOSH
      export STARTED_OOSH
      echo -e "${CYAN}applying new configuration - from debug $RETURN_VALUE ${NORMAL}" >/dev/tty
      export RETURN_VALUE
      $OOSH_DIR/this restart 
      #echo -e "${CYAN}exited onError ${ERROR_CODE_RECONFIG}${NORMAL}"
      exit $ERROR_CODE_RECONFIG
    fi

    if [ ! "$RETURN_VALUE" = "1" ]; then
      warn.log "GOT EXPECTED ERROR in function ${FUNCNAME[1]} in line: ${BASH_LINENO[1]} from ${BASH_SOURCE[2]} returned with ERROR code: $RETURN_VALUE"
    fi
    EXPECTED_RETURN_VALUE=1
    return 0
  fi

  oo cmd errno moreutils


  debug.log "source stack: ${BASH_SOURCE[@]##*/}"
  info.log "EXPECTED_RETURN_VALUE=$EXPECTED_RETURN_VALUE ? RETURN_VALUE=$RETURN_VALUE "
  error.log         "line ${BASH_LINENO[0]}: \"$2\" from ${BASH_SOURCE[1]} returned with ERROR code: $( errno $RETURN_VALUE )"
  if [ "$LOG_LEVEL" -gt 3 ]; then
    check.debug.level 3
    stackTrace
    check.debug.level reset
  fi   
}

expect.error()
{
  if (this.isNumber "$1"); then
    export EXPECTED_RETURN_VALUE=$1
  else
    warn.log "ignoring expect error, because \"$1\" is not a number."
  fi
}

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


function setTrap() {
  #echo "trap DEBUG set to step"

  #export PS4='\e[90m+${LINENO}: '


  #set -e
  trap 'onError ${?} ${BASH_COMMAND}' ERR
  trap 'onReturn ${?}' RETURN
  trap 'onExit  ${?}' EXIT 
  
  trap step DEBUG 2>/dev/null
}

if [ $LOG_LEVEL -lt 5 ]; then
  info.log "debug setTrap"
  setTrap
fi

