###############################################################################
#                             Driglibash pack 1
#                 Usual helper functions for bash scripts
#               https://github.com/adrianamaglio/driglibash
###############################################################################

# Set to true to make a pause at each step
driglibash_step_by_step=false

# Set to watever you want to have a prefix
driglibash_section_prefix=""


trap 'die "Received sigint"' INT

# Output on standard error output
yell() {
  echo >&2 -e "$@"
}

# Output first parameter, second parameter times
repeat() {
  printf "$1"'%.s' $(eval "echo {1.."$(($2))"}")
}

# Output a "section title" to visually separate different script part
# TODO local variables
section(){
  text="\033[00;36m$driglibash_section_prefix\033[0m$1"
  if [ -n "$text" ] ; then
    len="${#text}"
    max_len="$(($(tput cols)-2))"
    if [ "$len" -ge "$max_len" ] ; then
      right=5
      left=5
    else
	  left=4
      right="$(($max_len - $len - left))"
    fi
  else
    left=80
    right=0
  fi

  # If the character number was rounded down
  if [ "$(($left + $right + $len +1 ))" -eq "$max_len" ] ; then
    left="$(($left+ 1))"
  fi

  repeat '=' "$left"
  echo -ne " $text "
  if [ "$right" -ge 1 ] ; then
    repeat '=' "$right"
  fi
  echo

  if "$driglibash_step_by_step" ; then
    echo "Press enter to proceed"
    read
  fi
}
alias step=section

# Print an error, clean and exit
die() {
  yell "$@"
  clean
  exit 1
}

# Exit on error if not root
root_or_die() {
  if [ "$UID" -ne 0 ] ; then
    die "You need to be root"
  fi
}

# Execute a command and die if it returns with error #
run() {
  while true ; do
    "$@"
    code=$?
    if [ "$code" -ne 0 ] ; then
      yell "command [$*] failed with exit code '$code'"
      if [ -n "$driglibash_run_retry" ] ; then
        echo "Retry ? Retry (y), skip the command (s) or exit script(n) [Y/s/n] ?"
        read answer
        if [ "$answer" = "y" ] || [ "$answer" = "Y" ] || [ -z "$answer" ] ; then
          continue
        elif [ "$answer" = "s" ] || [ "$answer" = "S" ] ; then
          return "$code"
        fi
      fi
      die "Aborting"
    else
      break
    fi
  done
}


# Execute a commad in background and return its pid
start(){
  "$@" &
  pid=$!
  clean pre "kill $pid"
  return $pid
}

# Clean exit #
# Record command lines passed as argument and execute them all when called without args #
# One argument = One command #
# TODO append or prepend according to arg
declare -a driglibash_clean_actions
clean() {
  if [ "$#" -eq 0 ] ; then
    echo "Cleaning"
    for action in "${driglibash_clean_actions[@]}" ; do
      echo "driglibash_clean> $action"
      $action
    done
  elif [ "$#" -eq 1 ] ; then
    driglibash_clean_actions+=("$1")
  elif [ "$#" -eq 2 ] ; then
    case "$1" in
      "pre")
        declare -a tmp
        tmp=("${driglibash_clean_actions[@]}")
        driglibash_clean_actions=("$2")
        driglibash_clean_actions+=("${tmp[@]}")
        ;;
      "post")
        driglibash_clean_actions+=("$2")
        ;;
      "del")
        for i in "${!driglibash_clean_actions[@]}" ; do
          if [ "$2" = "${driglibash_clean_actions[$i]}" ] ; then
            unset driglibash_clean_actions[$i] 
            break
          fi
        done
        ;;
      *)
        die "driglibash_clean: action '$1' not supported"
    esac
  else
    die "driglibash_clean : Bad clean usage, receveid more than two args"
  fi
}

# tells where your executable is (absolute path). Follow simlinks if any argument provided
where() {
  if [ -z "$1" ] ; then
    echo "$( cd -P "$( dirname "$1" )" && pwd )"
  else
    SOURCE="$0"
    while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
      DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
      SOURCE="$(readlink "$SOURCE")"
      [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
    done
    DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
    
    echo $DIR
  fi  
}

# Add the line $1 in file $2 if not present
line_in_file() {
  if [ "$#" -ne 2 ] ; then die "Bad usage of 'line_in_file'. Got '$#' parameters : '$@'" ; fi
  if [ -z "$1" ] ; then die "Line arg is emtpy in 'line_in_file'" ; fi
  line="$1"
  if [ -z "$2" ] ; then die "File arg is emtpy in 'line_in_file'" ; fi
  file="$2"
  if [ ! -f "$file" ] ; then run touch "$file" ; fi

  grep -q -x -F "$line" "$file" || echo "$line" >> "$file"
}