#!/bin/bash

[[ "$TRACE" ]] && set -x

DEBUG=${DEBUG:-"Unknown Error"}

function log {
  now=`date +"%Y-%m-%d %T"`
  echo "[${now}] $1"
}

function usage {
cat <<-EOF
	Usage: $PROGNAME [OPTIONS] <local-path> <remote-path>
	Sync s3 directory locally and backup changed files on exit

	  --force-restore      restore even if local directory is not empty

	   eg: $PROGNAME /data s3://bucket/dir
EOF
}

function error_exit {
  log "${1:-"Unknown Error"}" 1>&2
  exit 1
}

PARSED_OPTIONS=$(getopt -n "$0" -o f --long "force-restore" -- "$@")
if [ $? -ne 0 ]; then
  exit 1
fi
eval set -- "$PARSED_OPTIONS"

while true; do
  case "$1" in
    -f|--force-restore)
      FORCE_RESTORE="true"
      shift;;

    --)
      shift
      break;;
  esac
done

PROGNAME=$0
S3_PROG=/s5cmd
LOCAL=$1
REMOTE=$2
WATCH_EVENTS=modify

function restore {
  if [ "$(ls -A $LOCAL)" ]; then
    if [[ ${FORCE_RESTORE:false} == 'true' ]]; then
      error_exit "local directory is not empty"
    fi
  fi

  log "restoring $REMOTE => $LOCAL"
  if ! $S3_PROG sync "$REMOTE/*" "$LOCAL"; then
    error_exit "restore failed"
  fi
}

function backup {
  log "backup $LOCAL => $REMOTE"
  if ! $S3_PROG sync "$LOCAL" "$REMOTE" $S3_SYNC_FLAGS; then
    log "backup failed" 1>&2
    return 1
  fi
}

function final_backup {
  log "backup $LOCAL => $REMOTE"
  while ! $S3_PROG sync "$LOCAL" "$REMOTE" $S3_SYNC_FLAGS; do
    log "backup failed, will retry" 1>&2
    sleep 1
  done
  exit 0
}

function idle {
  log "ready"
  log "RESTORE_INTERVAL: ${RESTORE_INTERVAL}"
  while true; do
    restore
    if [[ -v RESTORE_INTERVAL ]]; then
      backup
      timeout ${RESTORE_INTERVAL} inotifywait -m -e modify -e move -e create -e delete --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' $LOCAL | while read date time file; do log "The file '$file' appeared in directory '$path' via '$action'"; backup; done
    else
      log "Without restore interval"
      inotifywait -m -e modify -e move -e create -e delete --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' $LOCAL |
      while read date time file
      do
        log "The file '$file' appeared in directory '$path' via '$action'"
        backup
      done
    fi
  done
}

trap final_backup SIGHUP SIGINT SIGTERM
trap "backup; idle" USR1

idle