#!/bin/bash
#########################################################################
#        common - Utility file with common functions for updater        #
#                                                                       #
#                             Dependencies:                             #
#                                 bash                                  #
#                          coreutils (>=8.32)                           #
#                                  tar                                  #
#                                                                       #
#                                                                       #
#                       Author: Ethan Smith-Coss                        #
#                            Version: 0.1.4                             #
#                    Created: 2021-05-20T16:47+0100                     #
#                 Last Modified: 2021-06-22T16:57+0100                  #
#                                                                       #
#                 ####################################                  #
#                                                                       #
#        common - Utility file with common functions for updater        #
#                   Copyright ©️ 2021 Ethan Smith-Coss                   #
#                                                                       #
# This program is free software: you can redistribute it and/or modify  #
# it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation, either version 3 of the License, or   #
#                  (at your option) any later version.                  #
#                                                                       #
#    This program is distributed in the hope that it will be useful,    #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of     #
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     #
#             GNU General Public License for more details.              #
#                                                                       #
#   You should have received a copy of the GNU General Public License   #
# along with this program.  If not, see <http://www.gnu.org/licenses/>. #
#                                                                       #
#########################################################################

# logging function called to log information to a file.
function log {
	local log_out=$(realpath "${0%/*}/.log.1")
	[[ $# -eq 0 ]] && log "ERROR" "Log function was called without any arguments. Returning 1." "$log_out" && return 1
	[[ ! $# -eq 3 ]] && log "ERROR" "Log function expected at least 3 arguments, recieved $#. Returning 1." "$log_out" && return 1
	$(echo "$(date -Iseconds) ($1): $2" >> "$3") >/dev/null 2>&1
	[[ ! $? -eq 0 ]] && log "ERROR" "Log function encountered an issue writing to \"$3\". Returning 1." "$log_out" && return 1

	return 0
}

# archive function used to create an archive compression of Microsoft Edge
function archive_system {
	local log_out=$(realpath "${0%/*}/.log.1")
	[[ -e $1 ]] && log "ERROR" "Archive function was called without any arguments." "$log_out"
	
	local archive_output="/tmp/microsoft-edge-autoupdater/$(echo $1 | sed 's/\//_/').tar.gz"
	[[ -f "$archive_output" ]] && return 0
	
	## identify the files required for compressing
	usr_files="$(grep -E '^usr/.*beta.*$' "/tmp/microsoft-edge-autoupdater/Contents-amd64" | awk '{print "/" $1}')"
	opt_files="$(ls -1 "/opt/$1/" | sed -E "s/^(.*)$/\/opt\/"$(echo $1 | sed 's/\//\\\//')"\/\1/g")"
	### :@Ethan: we need to identify all the symlinked files and store them in a record. When we decompress we reinstate the symlinks.
	## This file is only stored temporarily and any symlinks will be removed from the identified files for compression.
	symlink_record="/tmp/microsoft-edge-autoupdater/symlink-record"
	ls -l $opt_files $usr_files | grep -Eo ':.*->.*$' | sed 's/\s->\s/:/g' | cut -d' ' -f2- > "$symlink_record"

	## remove identified symlink files from lists
	while read -r record ; do
		record=$(echo "$record" | cut -d: -f1)
		[[ "$record" =~ \/usr\/ ]] && record=$(echo $record | sed 's/\//\\\//g') && usr_files=$(echo "$usr_files" | sed "s/^"$record"$//") && continue
		[[ "$record" =~ \/opt\/ ]] && record=$(echo $record | sed 's/\//\\\//g') && opt_files=$(echo "$opt_files" | sed "s/^"$record"$//")
	done < <(cat $symlink_record)

	## use gzip compression to create the tarball archive
	tar --overwrite -czf "$archive_output" $opt_files $usr_files  > "/tmp/microsoft-edge-autoupdater/tar_dump.log" 2>>"$log_out"
	exit_code=$?
	[[ ! $exit_code -eq 0 ]] && { log "ERROR" "(Archive) There was an issue creating the archive file of system. Returning...(10)" "$log_out" ; return 10 ; }

	return 0
}

# restoration function called at any point when the update fails during an installation process.
function restore_files {
	local log_out=$(realpath "${0%/*}/.log.1")
	[[ -e $1 ]] && log "ERROR" "Restore function was called without any arguments." "$log_out"
	backup_file="/tmp/microsoft-edge-autoupdater/$1.tar.gz"
	[[ ! -f "$backup_file" ]] && { log "ERROR" "There is no backup of Microsoft Edge (Beta) identified. Restoration not possible." "$log_out" ; return 12 ; }

	## decompress the tarball archive using gzip and overwrite all files in the archive on the system
	tar --overwrite -xzf "$backup_file" -C "/" > "/tmp/microsoft-edge-autoupdater/tar_dump.log" 2>>"$log_out"
	exit_code=$?
	[[ ! $exit_code -eq 0 ]] && { log "ERROR" "There was an issue restoring pervious files to system." \
		"The backup created will not be removed to allow for manual restoration. Returning...(12)" ; return 12 ; }

	## recreate the symlinks
	log "DEBUG" "Re-establishing symlinks..." "$log_out"
	symlink_record="/tmp/microsoft-edge-autoupdater/symlink-record"
	while read -r record ; do
		symlink="$(echo $record | cut -d':' -f1)"
		symlink_to="$(echo $record | cut -d':' -f2)"
		### :NOTE: symlinks may already exist from new update and theoretically could be different in a newer version. Remove them first
		rm "$symlink"
		## create new sylinks based on the restored files
		ln -s "$symlink_to" "$symlink" >/dev/null 2>>"$log_out"
		exit_code=$?
		[[ ! $exit_code -eq 0 ]] && { log "ERROR" "There was an issue trying to create a symlink to "$symlink_to"" "$log_out" ; continue ; }
		log "DEBUG" "Successfully created symlink: "$symlink" -> "$symlink_to"" "$log_out"
	done < <(cat $symlink_record)
	log "DEBUG" "Symlinks re-established." "$log_out"

	return 0
}

# notification function used to send the user a notification via the dbus
function notify {
	local log_out=$(realpath "${0%/*}/.log.1")
	[[ $# -eq 0 ]] && log "ERROR" "Notify function was called without any arguments. Returning 1." "$log_out" && return 1
	[[ ! $# -eq 2 ]] && log "ERROR" "Notify function expected at least 2 arguments, recieved $#. Returning 1." "$log_out" && return 1
	notify-send "$1" "$2" >>"$log_out" 2>&1 && tput bel
	exit_code=$?
	[[ ! $exit_code -eq 0 ]] && log "ERROR" "There was an issue send a notification to the system." "$log_out"

	return 0
}
