#!/usr/bin/env bash
#clear
#export PS4='\e[90m+${LINENO} in ${#BASH_SOURCE[@]}>${FUNCNAME[0]}:${BASH_SOURCE[@]##*/} \e[0m'
#set -x

#echo "starting: $0 <LOG_LEVEL=$1>"

### new.method

backup.usage()
{
  local this=${0##*/}
  echo "You started 
$0

  Usage:
  $this: command   description and Parameter

      usage     prints this dialog while it will print the status when there are no parameters          
      v         print version information
      
      list
      list.config
      config.list      lists the configuration

      to               <directory> sets the backup target directory                 and saves the configuration
      from             <directory> sets the root source directroy to be backuped    and saves the configuration
      strategy         stes the startegy.... use Tab Completion to find out values  and saves the configuration

      diff             <?directory> compares SOURCE/<?directory> to TARGET/<?directory> ${RED}not recursively...only flat${NORMAL}
      full.diff        same but recursively  ${yellow}can tike some time${NORMAL}

      run              runs the rsync backup for the given <dir>

      inspect          inspects the current backup process log file so that yo can follow a long lasting process

      list.last.diff.result     all following command work on the last result 
      list.last.result.raw

      list.notBackuped
      list.onlyInSource

      list.onlyInBackup
      list.onlyInTarget

      list.same         user Tab Completion to prevent the warning
  
  Examples
    $this v
    $this init

    $this list
    $this from /Users/Shared/TimeMachine/Sicherung
    $this to /Volumes/myData/Devices/McDonges.native/TimeMachine/Sicherung/
    $this strategy full
    $this capture.log.mode full
    $this list
  "
}

backup.from()  # <fromPath="/"> # sets the root for bakups (normally "/")
{
  export BACKUP_SOURCE="$1"
  shift
  backup.config.save
  RETURN="$1"
}


backup.to()  # <toPath="/media/disk1/backups"> # sets the bakups location on a share or an external disk
{
  export BACKUP_TARGET="$1"
  shift
  backup.config.save
  RETURN="$1"
}

backup.strategy()  # <strategy> # sets the backup strategy as one of: incremental, full, secureMuve, replaceFoldersByLinks
{
  if [ -z "$1" ]; then
    important.log "current BACKUP_STRATEGY: $BACKUP_STRATEGY"
    return 0
  fi
  export BACKUP_STRATEGY="$1"
  shift
  backup.config.save
  RETURN="$1"
}

backup.strategy.completion() 
{
  echo -e "full \\nincremental \\nsecureMove \\nreplaceByFolderLinks " | grep "^$1" 
}

backup.capture.log.mode() # <logMode> # set the log mode as one of: slient, full, screen, none
{
  if [ -z "$1" ]; then
    important.log "current BACKUP_CAPTURE_LOG_MODE: $BACKUP_CAPTURE_LOG_MODE    and command: $BACKUP_CAPTURE_LOG_COMMAND"
    return 0
  fi
  export BACKUP_CAPTURE_LOG_MODE="$1"
  shift
  private.check.log.mode

  backup.config.save
  RETURN="$1"
}

private.check.log.mode() 
{
  case "$BACKUP_CAPTURE_LOG_MODE" in
    "full")
      export BACKUP_CAPTURE_LOG_COMMAND="capture.log"
      ;;
    "silent")
      export BACKUP_CAPTURE_LOG_COMMAND="capture.log.silent"
      ;;
    "none"|"screen")
      export BACKUP_CAPTURE_LOG_COMMAND=""
      ;;
  esac
}

backup.parameter.completion.logMode() 
{
  echo -e "full \\nsilent \\nnone \\nscreen " | grep "^$1" 
}




backup.from.completion() 
{
  compgen -o nospace -o dirnames  "$1" | grep "^$1" 
}

backup.to.completion() 
{
  private.complete.folders "$1"
}


private.complete.folders() 
{
  #https://unix.stackexchange.com/questions/151118/understand-compgen-builtin-command
  compgen -o dirnames "$1" | grep "^$1" 
}

backup.config.list() 
{
  config list backup 
}

backup.config.save() 
{
  config save backup BACKUP_
}

backup.run()  # <?dir> # backups the directroy (which you are in) to the backup location
{
  local backup_source="${BACKUP_SOURCE/\//}"
  console.log "...backup_source: $backup_source"
  
  backup.get.backupPath "$1" >/dev/null
  local path="$RESULT"
  console.log "...path: $path"

  if ! [ -d "$BACKUP_TARGET/$path" ]; then
    silent.log "creatded $BACKUP_TARGET/$path"
    mkdir -p "$BACKUP_TARGET/$path"
  fi
  console.log "...BACKUP_TARGET: $BACKUP_TARGET$path/.."
  console.log "...BACKUP_CAPTURE_LOG_COMMAND: $HOME/oosh/$BACKUP_CAPTURE_LOG_COMMAND"

  $BACKUP_CAPTURE_LOG_COMMAND sudo rsync -zavh -progress /"$backup_source$path" "$BACKUP_TARGET$path/.."
}

backup.parameter.completion.dir() 
{
  info.log "backup.parameter.completion.dir $*"
  c2 folders.completion "$1"
}

backup.diff()   # <dir> # logs the brief diff btween the current deirectory and the backup location
{
  ## ${ENV/serchPattern/replaceValue}  replace first only
  ## ${ENV//serchPattern/replaceValue} replace all
  local backup_source="${BACKUP_SOURCE/\//}"
  debug.log "backup_source: $backup_source"
  
  backup.get.backupPath "$1"  >/dev/null
  local path="$RESULT"

  debug.log "path: $path"

  if [ "$backup_source/" = "//" ]; then
    backup_source=""
  fi
  debug.log "backup_source after : $backup_source"
  
  $BACKUP_CAPTURE_LOG_COMMAND diff -q --brief "$backup_source/$path" "$BACKUP_TARGET/$path"
  #diff -q --brief "$backup_source/$path" "$BACKUP_TARGET/$path" > >(tee -a $CONFIG_PATH/result.txt) 2> >(tee -a $CONFIG_PATH/result.txt $CONFIG_PATH/error.txt >&2)
  #vimdiff "$backup_source/$path" "$BACKUP_TARGET/$path" 
  
  backup.list.last.diff.result
}

backup.full.diff()   # <dir> # logs the full diff btween the current deirectory and the backup location
{
  ## ${ENV/serchPattern/replaceValue}  replace first only
  ## ${ENV//serchPattern/replaceValue} replace all
  local backup_source="${BACKUP_SOURCE/\//}"
  debug.log "backup_source: $backup_source"
  
  local path="${1/\//}"
  debug.log "path: $path"

  if [ "$backup_source/" = "//" ]; then
    backup_source=""
  fi
  debug.log "backup_source after : $backup_source"               # write to console AND result.text AND wite errors to errot.txt AND result.txt
  $BACKUP_CAPTURE_LOG_COMMAND diff -qr --brief "$backup_source/$path" "$BACKUP_TARGET/$path" > >(tee -a $CONFIG_PATH/result.txt) 2> >(tee -a $CONFIG_PATH/result.txt $CONFIG_PATH/error.txt >&2)
  backup.list.last.diff.result no-warn
}

backup.inspect() 
{
  tail -f $CONFIG_PATH/result.txt
}

backup.list.errors()  # # logs the latest errors
{
  cat $CONFIG_PATH/error.txt | xargs -I {} printf "$RED%s\n" {}
  console.log "$NORMAL"
}

backup.list.last.result.raw()  # # logs the latest run
{
  cat $CONFIG_PATH/result.txt
}

backup.list.last.diff.result()  # # logs the latest diff
{
  backup.list.onlyInSource
  backup.list.onlyInTarget
  backup.list.same "$1"
}

backup.list.onlyInSource() 
{
  cat $CONFIG_PATH/result.txt | grep "Only in $backup_source/$path" | xargs -I {} printf "$YELLOW%s\n" {}
  console.log "$NORMAL"
}
backup.list.onlyInTarget() 
{
  cat $CONFIG_PATH/result.txt | grep "Only in $BACKUP_TARGET/$path" | xargs -I {} printf "$CYAN%s\n" {}
  console.log "$NORMAL"
}

backup.list.onlyInBackup() 
{
  backup.list.onlyInTarget
}

backup.list.notBackuped() 
{
  backup.list.onlyInSource
}

backup.list.same() 
{
  cat $CONFIG_PATH/result.txt | grep "Common " | xargs -I {} printf "$GREEN%s\n" {}

  if [ -z "$1" ]; then
    console.log "
    ${YELLOW}The ${GREEN}green files are common, ${YELLOW}but this does ${RED}not${YELLOW} guarantee that they are the ${RED}same${NORMAL} RECURSIVELY
    fot that use 
    
    ${GREEN}backup full.diff
    "
  fi
  console.log "$NORMAL"
}

backup.replace.same.with.folderLinks() 
{
  backup.list.same no-warn | sed 's/\(Common subdirectories: \)\(.*\)\( and \)\(.*\)/private.replace.by.folderLink \"\4\" \"\2\"\n/' | xargs
}

backup.replace.by.folderLink() 
{
  backup.get.backupPath "$1" >/dev/null

  local backup_source="${BACKUP_SOURCE/\//}"
  info.log "Path absolute local: $backup_source/$RESULT"
  info.log "Path      in Backup: $backup_source/$RESULT"
  private.replace.by.folderLink $BACKUP_TARGET/$RESULT $backup_source/$RESULT

}

backup.replace.by.folderLink.completion() 
{
    compgen -o dirnames "$1" | grep "^$1" 
}

private.replace.by.folderLink() 
{
  mv "${2}" "${2}.isBackuped"
  ln -s "$1" "${2}.lnk"
  ln -s "$1" "${2}"
  important.log "Please check result:"
  ls -al "$2/.."
}

backup.get.backupPath()  # <dir="."> # prints the backupPath
{
  local path="$1"
  if [ -z "$path" ]; then
    path="."
  fi

  this.absolutePath "$path"
  local path=$RESULT

  info.log "$1 system absolute path: $path"

  export RESULT=${path/$BACKUP_SOURCE/}
  info.log "$1 backup relative path: $RESULT"
  echo $RESULT
}

backup.get.backupPath.completion() 
{
    compgen -o dirnames "$1" | grep "^$1" 
}


backup.list.same.completion() 
{
  echo -e "no-warn-for-pipe" | grep "^$1" 
}

backup.diff.completion() 
{
  local backup_source="${BACKUP_SOURCE/\//}"
  local path="${1/\//}"
  #echo path: $path
  if [ "$backup_source" = "/" ]; then
    backup_source=""
  fi
  compgen -o dirnames "$backup_source/$path" | grep "^$backup_source/$path" 
}

backup.list() 
{
  backup.list.config
}


backup.list.config() 
{
  console.log "${YELLOW}from Source: 
  $BACKUP_SOURCE
  "
  console.log "${CYAN}to Target:
  $BACKUP_TARGET
  "

  console.log "${NORMAL}Strategy:
  ${WHITE}$BACKUP_STRATEGY${NORMAL}
  "


  console.log "${NORMAL}Log Capture Mode:
  ${WHITE}$BACKUP_CAPTURE_LOG_MODE${NORMAL}
  "
}

backup.start()
{
  #echo "sourcing init"
  source this
  source $CONFIG_PATH/backup.env
  private.check.log.mode
  #source config

  # if [ -z "$1" ]; then
  #   status.discover "$@"
  #   return 0
  # fi

  this.start "$@"
}

backup.start "$@"

