#!/bin/sh
 
usage() {
   echo "Usage: backup [--noninteractive] [--full] [filename]"
   echo ""
   echo "  e.g. ./backup                     << Makes a file with a timed filename"
   echo "       ./backup myBackup.zip        << Makes a file called myBackup.zip"
   echo "       ./backup --full              << Makes a full backup file with a timed filename"
   echo "       ./backup --full myBackup.zip << Makes a full backup file called myBackup.zip"
   echo "       ./backup --noninteractive    << Makes a backup file which is downloadable from"
   echo "                                       http://<host_ip>:$OPENHAB_HTTP_PORT/static/$sWebFile"
   echo "       ./backup --noninteractive myBackup.zip"
   echo "                                    << Makes a backup file which is downloadable from"
   echo "                                       http://<host_ip>:$OPENHAB_HTTP_PORT/static/myBackup.zip"
   echo ""
   echo "Use this script to backup your openHAB configuration, you can use the 'restore' script"
   echo "from any machine to transfer your configuration across to another instance."
   echo ""
   echo "The noninteractive flag allows backups to be run from an OpenHAB GUI button,"
   echo "that uses the Exec Binding, and a command like: openhab-cli backup --noninteractive"
   echo ""
   echo "A full backup must be done in interactive mode, and includes the tmp and cache directories"
   echo "that are normally excluded."
   echo ""
   echo "Backup directory: '$OPENHAB_BACKUPS'"
   echo "Set \$OPENHAB_BACKUPS to change the default backup directory."
   echo "Backup temporary directory: '$OPENHAB_BACKUPS_TEMP'"
   echo "Set \$OPENHAB_BACKUPS_TEMP to change the default backup temporary directory."
}

getFullPath() {
  specDir="$(dirname "$1")"
  if cd "$specDir" 2>/dev/null; then
    OutputFile="$(pwd)/$(basename "$1")"
  else
    echo "Unable to locate specified directory '$specDir'"
    exit 1
  fi
}

# Defaults
bFull="0"
bInteractive="1"
sZipFile=""
sWebFile="latest_backup.zip"

setup(){
  while [ "$1" != "" ]; do
    case $1 in
        -h | --help)
            usage
            exit 0
            ;;
        --full)
            bFull="1"
            ;;
        --noninteractive)
            bInteractive="0"
            ;;
        *)
            sZipFile="$1"
            ;;
    esac
    shift
  done

  if [ $bInteractive = "0"  ];then
    if [ "$bFull" = "1" ];then
        echo "Full backup must be run interactively. Exiting." >&2
        exit 1
    fi
    OPENHAB_USERDATA="/var/lib/openhab"
  else
    ## Ask to run as root to prevent us from running sudo in this script.
    if [ "$(id -u)" -ne 0 ]; then
     echo "Please run this script as root! (e.g. use sudo)" >&2
     exit 1
    fi
  fi

  command -v zip >/dev/null 2>&1 || {
    echo "'zip' program was not found, please install it first." >&2
    exit 1
  }

  ## Set path variables
  if [ -r /etc/profile.d/openhab.sh ]; then
    . /etc/profile.d/openhab.sh
  elif [ -r /etc/default/openhab ]; then
    . /etc/default/openhab
  fi

  if [ "$bInteractive" = "0" ];then
    OPENHAB_BACKUPS="$OPENHAB_USERDATA/backup_user"
    OPENHAB_BACKUPS_TEMP="$OPENHAB_USERDATA/tmp/backup"
  fi

  WorkingDir="$(cd "$(dirname "$0")" && cd ../.. && pwd -P)"

  if [ -z "$OPENHAB_CONF" ];  then OPENHAB_CONF="$WorkingDir/conf"; fi
  if [ -z "$OPENHAB_USERDATA" ]; then OPENHAB_USERDATA="$WorkingDir/userdata"; fi
  if [ -z "$OPENHAB_BACKUPS" ]; then OPENHAB_BACKUPS="$WorkingDir/backups"; fi
  if [ -z "$OPENHAB_RUNTIME" ]; then OPENHAB_RUNTIME="$WorkingDir/runtime"; fi

  if [ "$bInteractive" = "1" ];then
    echo "Using '$OPENHAB_CONF' as conf folder..."
    echo "Using '$OPENHAB_USERDATA' as userdata folder..."
    echo "Using '$OPENHAB_RUNTIME' as runtime folder..."
  fi
  fileList="$OPENHAB_RUNTIME/bin/userdata_sysfiles.lst"

  ##  Apply arguments
  if [ "$bFull" = "1" ]; then
    INCLUDE_CACHE="true"
     [ "$bInteractive" = "1" ] && echo "including cache"
  fi

  timestamp=$(date +"%y_%m_%d-%H_%M_%S")
  ## Set the filename
  if [ "$bInteractive" = "0" ];then
    [ -n "$sZipFile" ] && sWebFile=$sZipFile
    OutputFile="/etc/openhab/html/$sWebFile"
    [ -e "$OutputFile" ] && rm $OutputFile
  elif [ -z "$sZipFile" ];then
    [ "$bInteractive" = "1" ] && echo "Using '$OPENHAB_BACKUPS' as backup folder..."
    OutputFile="$OPENHAB_BACKUPS/openhab-backup-$timestamp.zip"
  else
    getFullPath "$sZipFile"
  fi

  [ "$bInteractive" = "1" ] && echo "Writing to '${OutputFile}'..."

  ## Check two of the standard openHAB folders to make sure we're backing up the right thing.
  if [ ! -d "$OPENHAB_USERDATA" ] || [ ! -d "$OPENHAB_CONF" ]; then
    echo "Configuration paths are invalid..." >&2
    echo "Try setting OPENHAB_USERDATA and OPENHAB_CONF environment variables." >&2
    exit 1
  fi

  ## Find the group and user of the current openHAB folders.
  OHUser=$(ls -ld "$OPENHAB_USERDATA" | awk '{print $3}')
  OHGroup=$(ls -ld "$OPENHAB_USERDATA" | awk '{print $4}')

  CurrentVersion="$(awk '/openhab-distro/{print $3}' "$OPENHAB_USERDATA/etc/version.properties")"

  ## Store anything in temporary folders
  # Check if we should use TempDir from env $OPENHAB_BACKUPS_TEMP
  if [ -n "${OPENHAB_BACKUPS_TEMP}" ]; then
    TempDir="$OPENHAB_BACKUPS_TEMP";
  else
    TempDir="/tmp/openhab/backup"
  fi
  [ "$bInteractive" = "1" ] && echo "Making Temporary Directory if it is not already there"
  if [ ! -d "$TempDir" ]; then
    mkdir -p "$TempDir" || {
    echo "Failed to make temporary directory: $TempDir" >&2
    exit 1
    }
  fi
  [ "$bInteractive" = "1" ] && echo "Using $TempDir as TempDir"

  ## Clear older stuff if it exists
  rm -rf "${TempDir:?}/"*
}

setup $@

if [ "$bInteractive" = "1" ];then
   echo "                                         "
   echo "#########################################"
   echo "          openHAB backup script          "
   echo "#########################################"
   echo "                                         "
fi


## Set backup properties file.
{
  echo "version=$CurrentVersion"
  echo "timestamp=$timestamp"
  echo "user=$OHUser"
  echo "group=$OHGroup"
} > "$TempDir/backup.properties"

## Copy userdata and conf folders
[ "$bInteractive"  = "1" ] && echo "Copying configuration to temporary folder..."
mkdir -p "$TempDir/userdata"
if [ -z "$INCLUDE_CACHE" ]; then
  find "${OPENHAB_USERDATA:?}/"* -prune -not -path "${OPENHAB_BACKUPS:?}" -and -not -path '*/tmp' -and -not -path '*/cache' | xargs -I % cp -R % "$TempDir/userdata"
else
  find "${OPENHAB_USERDATA:?}/"* -prune -not -path "${OPENHAB_BACKUPS:?}" | xargs -I % cp -R % "$TempDir/userdata"
fi
mkdir -p "$TempDir/conf"
cp -a "${OPENHAB_CONF:?}/"*      "$TempDir/conf"

## Remove non-transferable userdata files
[ "$bInteractive" = "1" ] && echo "Removing unnecessary files..."
if [ -f "$fileList" ]; then
  while IFS= read -r fileName
  do
    rm -rf "$TempDir/userdata/etc/$fileName"
  done < "$fileList"
else
  echo "System Filelist not found, exiting..."
  exit 1
fi

## Create archive
mkdir -p "$OPENHAB_BACKUPS"
[ "$bInteractive"  = "1" ] && echo "Zipping folder..."

## Jump into directory before making zip
## Cleans file structure
( cd "$TempDir" || exit
  zip -qr "$OutputFile" . || {
    echo "zip failed to store a backup."
    exit 1
  }
) || exit 1

[ "$bInteractive" = "1" ] && echo "Removing temporary files..."
rm -rf $TempDir

if [ "$bInteractive" = "0" ];then
  echo "http://$(cat /etc/hostname):$OPENHAB_HTTP_PORT/static/$sWebFile"
else
  echo "Success! Backup made in $OutputFile"
  echo ""
fi
