#!/usr/bin/env bash
# script-backup-prefix
# Steps:
# 1. Set Total Backup size variable
# 2. Prepare Prefix Name
# 3. Suggest and Ask for wzt file name
# 4. Ask user to select backup target/destination directory
# 5. Check available disk space in target directory before backing up
# 6. Ask for Compression Levels
# 7. Create wzt = tar.zst file
# 8. Show info about created wzt file
script-backup-prefix()
{
  dbug "I: Script: Launched ${FUNCNAME[0]}"
  
  SOURCE "script-check-variables-loaded-or-not"
  script-check-variables-loaded-or-not
  # needed? # SOURCE "winezgui-backup-restore-function"
  # 1. Set Total Backup size variable
  TOTAL_SIZE=$(expr ${PREFIX_SIZE_IN_BYTES})
  TOTAL_SIZE_IN_HF=$(echo ${TOTAL_SIZE} | numfmt --to iec)

  dbug "I: Script: ${FUNCNAME[0]}: Prefix Size: ${TOTAL_SIZE_IN_HF}"

  # 2. Prepare Prefix Name
  # 2.1 Format filename for flatpak or system install type

  if [ "${INSTALL_TYPE}" = "flatpak" ]; then
       # If "flatpak-" is not part of flatpak name
       # like WineZGUI flatpak name: io.github.fastrizwaan.WineZGUI, add it
       if ! [[ "$SHORT_FLATPAK_NAME" == *"flatpak-"* ]]; then
            SHORT_FLATPAK_NAME="flatpak-${SHORT_FLATPAK_NAME}"
       fi
       unset FILENAME 
       FILENAME+="${PROGNAME}-${APP_WITH_VER}"
       # if exe file is within prefix dir then it is a game bundle
       if [[ "${EXE_FILE}" == *"${PREFIXDIR}"* ]] ; then
           dbug "I: Script: ${FUNCNAME[0]}: Game Directory inside Prefix, changing name to game-bundle!"
           FILENAME+="-Game-Bundle"
       else
           FILENAME+="-Prefix-Backup"
       fi
       # Do not use flatpak name in wzt file
     #   FILENAME+="${SHORT_FLATPAK_NAME}"
       FILENAME+="-${DATE}"
       FILENAME+=".${BKP_EXT}"
       # Flatpak: Game-WineZGUI-0.87-Prefix-Backup-flatpak-wine7-20220904_2359.wzt
  else # for system add wine-version
       unset FILENAME
       FILENAME+="${PROGNAME}-${APP_WITH_VER}"
       # if exe file is within prefix dir then it is a game bundle
       if [[ "${EXE_FILE}" == *"${PREFIXDIR}"* ]] ; then
           dbug "I: Script: ${FUNCNAME[0]}: Game Directory inside Prefix, changing name to game-bundle!"
           FILENAME+="-Game-Bundle-"
       else
           FILENAME+="-Prefix-Backup-"
       fi
       FILENAME+="${WINEVER}"
       FILENAME+="-${DATE}"
       FILENAME+=".${BKP_EXT}"
       # Game-WineZGUI-0.87-Prefix-Backup-wine-7.0-20220904_2359.wzt
  fi

  # remove spaces->_ from FILENAME
  FILENAME=$(echo ${FILENAME}|tr " " "_")
  dbug "I: Script: ${FUNCNAME[0]}: Filename Suggestion: ${FILENAME}"

  # For Zenity prompt
  unset TITLE
  unset TEXT
  TITLE="Backup ${PREFIXNAME} Prefix!"
  TEXT+="${PREFIX_SIZE_IN_HF} ${PREFIXDIR}"

  # Zenity 4 looks good
  # 3. Suggest and Ask for wzt file name
  dbug "I: Script: ${FUNCNAME[0]}: Asking filename"
  BACKUP_FILE=$(${ZENITY_CMD}                         \
                 --title="${TITLE}"            \
                 --width=700 --height=30       \
                 --text="${TEXT}"              \
                 --entry-text="${FILENAME}"    \
                 --entry)

  # 3.1: if backup file is empty / cancel clicked
  if [ -z "${BACKUP_FILE}" ]; then
       dbug "I: Script: ${FUNCNAME[0]}: Cancelled!"
       unset BACKUP_FILE
       unset FILENAME
       Script_Window
  fi
  
  # Check if user entered symbols
  SOURCE "winezgui-check-entry-text"
  winezgui-check-entry-text "${BACKUP_FILE}"
  
  ENTRY_CHECK=$?
  if [ ${ENTRY_CHECK} -eq 1 ]; then
       dbug "I: Script: ${FUNCNAME[0]}: Symbols used in filename, cancelling!"
       return 1
  fi
  
  # 4. Ask user to select backup target/destination directory
  dbug "I: Script: ${FUNCNAME[0]}: Select backup directory"
  unset TITLE
  TITLE="Choose Backup Directory for ${BACKUP_FILE}!"
  TARGET_DIR=$(${ZENITY_CMD}  --file-selection --title="${TITLE}" --directory)
  if [ -z "${TARGET_DIR}" ]; then
       dbug "I: Script: ${FUNCNAME[0]}:" \
            "Select backup directory: Cancelled!"
       Script_Window
  fi

  # 4.1: Check if the target directory is writable or not?
  if [ ! -w "${TARGET_DIR}" ]; then
       echo "E: Script: ${FUNCNAME[0]}: ${TARGET_DIR} not writable"
       ${ZENITY_CMD} --error --no-wrap --title="Backup Error!" \
            --text "${TARGET_DIR} not writable\nAborting Backup!"
       Script_Window
  fi


  # 4.2 Required extension is .${BKP_EXT} i.e., .wzt, if not found add it
  dbug "I: Script: ${FUNCNAME[0]}: Given ${BACKUP_FILE}"

  if ! [[ "${BACKUP_FILE}" == *".${BKP_EXT}" ]]; then
       BACKUP_FILE="$(echo ${BACKUP_FILE}.${BKP_EXT})"
       dbug "I: Script: ${FUNCNAME[0]}: added suffix ${BKP_EXT}"
  fi

  dbug "I: Script: ${FUNCNAME[0]}: Using ${BACKUP_FILE}"

  # 5. Check available disk space in target directory before backing up
  # to make sure that prefix size < target dir for backup to start

  # Step 5.1: Get available target dir partition's available space in
  # Human format (df -h)
  dbug "I: Script: ${FUNCNAME[0]}: Determining available space"
  AVAILABLE_SPACE=$(df -h "${TARGET_DIR}"|tr -s " "|tail -n1|cut -f4 -d " ")
  #Check whether df gave a value or not
  if [ -z "${AVAILABLE_SPACE}" ]; then
       echo "-------------------- Error --------------------------"
       echo "Error: ${FUNCNAME[0]}: AVAILABLE_SPACE not assigned"
       echo "-------------------- Error --------------------------"
  fi
  dbug "I: Script: ${FUNCNAME[0]}: Available space: ${AVAILABLE_SPACE}"

  # Step 5.2: Convert the above $AVAILABLE_SPACE into bytes for comparison
  AVAILABLE_SPACE_IN_BYTES=$(echo ${AVAILABLE_SPACE}|numfmt --from iec)

  # Step 5.3: If Target directory does not have sufficient space, abort backup
  dbug "I: Script: ${FUNCNAME[0]}: Checking if size < target dir space"
  if [ ${AVAILABLE_SPACE_IN_BYTES} -gt ${TOTAL_SIZE} ]; then
       dbug "I: Script: ${FUNCNAME[0]}: ${TARGET_DIR} has enough disk space!"
  else
       echo "W: Script: ${FUNCNAME[0]}: ${TARGET_DIR} does not have disk space!"
       unset MSG
       unset TITLE
       TITLE="Not Enough Disk Space!"
       MSG+="${TARGET_DIR} has only ${AVAILABLE_SPACE}"
       MSG+=" "
       MSG+="free disk space left!\n"
       MSG+="Prefix backup requires ${TOTAL_SIZE_IN_HF} free disk space."

       # Warn user
       ${ZENITY_CMD} --warning --no-wrap --title "${TITLE}" --text "${MSG}"
       echo "E: Script: ${FUNCNAME[0]}: Not Enough Disk Space," \
            "Cancelled!"
       Script_Window

  fi

  # 6. Ask for Compression Levels
  unset LEVEL
  LEVEL=$(${ZENITY_CMD} --scale --value 10 --min-value 1 --max-value 19 \
       --text "${BACKUP_FILE}" --title "Select Compression Level...")
  # Exit if Cancel is clicked
  if [ -z "${LEVEL}" ]; then
       dbug "I: Script: ${FUNCNAME[0]}: Cancel Selected!"
       Script_Window
  fi
  dbug "I: Script ${FUNCNAME[0]}: Compression Level ${LEVEL} Selected!"

  # 7. Create wzt = tar.zst file
  # 7.1 Change directory to PREFIXES_DIR
  cd "${PREFIXES_DIR}"
  dbug "I: Script: ${FUNCNAME[0]}: Preparing files"

  # 7.2 Preprocess PREFIXDIR files (remove user name from files)
  SOURCE "winezgui-identity-remove"
  winezgui-identity-remove "${PREFIXDIR}"

  # Remove Identities from files
  # Find other files which has username in it.
  SOURCE "winezgui-identity-remove-from-drive-c-files"
  winezgui-identity-remove-from-drive-c-files "${PREFIXDIR}"

  # 7.3 Create wzt-info.yml for restore prompt requied for restoring wzt file.
  SOURCE "winezgui-create-wzt-info"
  winezgui-create-wzt-info "${PREFIXDIR}"
  

  # Find Local Tar and ZSTD command
  if [ $(which tar) ] && [ $(which zstd) ]; then
       TAR_CMD="$(which tar)"
  fi

  dbug "I: Script: ${FUNCNAME[0]}: Creating ${BACKUP_FILE} file..."
  
  dbug "-------------------------------------------------------------------"
  dbug "WZT_FILE_NAME=$WZT_FILE_NAME"
  dbug "Command:"
  dbug "${TAR_CMD} -I \"zstd -${LEVEL} -T0\" -cf \"${TARGET_DIR}/${BACKUP_FILE}\" \
                               -C \"${PREFIXDIR}\"  \"${WZT_FILE_NAME}\"   \
                               -C \"${PREFIXES_DIR}\" \"${PREFIXNAME}\" "
  dbug "-------------------------------------------------------------------"
  # Report user the time it took to bundle
  TIMER_START=${SECONDS}
  # 7.4 Create Backup archive and restore changes as soon as tar is done
  # add wzt-info.yml 1st then the prefix directory to the wzt file
  (${TAR_CMD} -I "zstd -${LEVEL} -T0" -cf "${TARGET_DIR}/${BACKUP_FILE}"       \
                               --exclude="registry_backup*.gz" \
                               -C "${PREFIXDIR}"  "${WZT_FILE_NAME}"    \
                               -C "${PREFIXES_DIR}" "${PREFIXNAME}" &)| \
  ${ZENITY_CMD}    --progress --pulsate --auto-close        \
            --title="Creating ${PREFIXNAME} backup!" \
            --width=500 --text="${BACKUP_FILE}..."
  TOOK=$(( SECONDS - ${TIMER_START} ))
  dbug "I: Script: Backup: Time Taken: $(date -d@${TOOK} -u +%H:%M:%S)"

  # 7.5 If user clicks cancel, kill tar commands
  # zenity progress won't kill the process, so we do it
  # find the pid of tar which is working with ${BACKUP_FILE}, else it will kill
  # other wzt file operation like extraction and backup
  PID_OF_TAR=$(ps -aux|grep tar|grep -i "${BACKUP_FILE}"           \
              |sed "/.*grep -i.*/d"|sed "s/  */ /g" |cut -f2 -d " ")
              
  # If there is a PID_OF_TAR then we need to kill the tar command
  if ! [ -z "${PID_OF_TAR}" ]; then
       kill -9 ${PID_OF_TAR} \
            && dbug "I: Script: ${FUNCNAME[0]}: Cancelled! Killed tar!" \ &&
       rm -f "${TARGET_DIR}/${BACKUP_FILE}" && \
            dbug "I: Script: ${FUNCNAME[0]}: Removed partial ${BACKUP_FILE}"

       # Backup Sucess Message
       MSG=("${PREFIXNAME} backup cancelled!")
  else
       # If no pid is found, that means wzt=tar.zst is created successfully
       dbug "I: Script: ${FUNCNAME[0]}: Created ${BACKUP_FILE}, Success!"
       # 7.6  Crate message
       BACKUP_SIZE=$(du -sh "${TARGET_DIR}/${BACKUP_FILE}"|cut -f1)
       # Check du value assignment
        if [ -z "${BACKUP_SIZE}" ]; then
            echo "-------------------- Error --------------------------"
            echo "Error: ${FUNCNAME[0]}: BACKUP_SIZE not assigned"
            echo "-------------------- Error --------------------------"
        fi
       # Backup Sucess Message
       MSG=("<b>Prefix: </b> ${PREFIXNAME}\n")
       MSG+="<b>Filename:</b> ${BACKUP_FILE}"
       MSG+="\n<b>Location:</b> ${TARGET_DIR}\n"
       MSG+="<b>Backup Size:</b> ${BACKUP_SIZE}"

  fi

  # 7.7 Restore changed values after backup
  dbug "I: Script: ${FUNCNAME[0]}: Restoring Registry and Info files"
  SOURCE "winezgui-identity-restore"
  winezgui-identity-restore "${PREFIXDIR}"
 
  # Find other files which has username in it.
  SOURCE "winezgui-identity-restore-from-drive-c-files"
  winezgui-identity-restore-from-drive-c-files "${PREFIXDIR}"

  dbug "I: Script: ${FUNCNAME[0]}: Created ${BACKUP_FILE} at ${TARGET_DIR}"

  # 8. Show info about created wzt file
  ${ZENITY_CMD} --no-wrap --info --title="Prefix Backup!" --text="${MSG[@]}"
}
