#!/bin/bash
#Reset error count and set as integer.

COMMONVERSION=1.2.0
declare -i ELINE
declare -i ERR
ERR=0
declare -i WARN
WARNINGS=0
declare -i DISTANCE
DISTANCE=0
declare -i INFORMATION
INFOFORMATION=0
declare -i RR
RR=0
declare -i TT
TT=0
declare -i CALC
CALC=0
declare -i EXITCOL
EXITCOL=0

# RAMDATA
# mounts loaded to zram:
mounts_zram=''

# mounts ignored:
mounts_null=''

# prompt default:
ps_default=no

# prompt timout:
ps_timeout=8

# minimum MiB free ram:
ram_min=750

# minimum MiB free zram:
zram_min=250

# preferred MiB free ram:
ram_pref=4000

# maximum MiB free zram:
zram_max=1000
# Suppression?
SUPPRESS=$(echo "$*" | grep "suppress")
PROMPTSUPPRESSION=$(echo "$@" | grep "prompt")

# Check for support of Repostorm
REPOSTORM=$(type -p repostorm)

# Root?
if [[ "${EUID}" -ne 0 ]]; then
	ISROOT=""
	else
	ISROOT=true
fi

# Check O/S Support
if [[ -f "/etc/os-release" ]]; then
	ISARCH=$(grep -i "arch" "/etc/os-release")
	ISULTIMATE=$(grep -i "ultimate" "/etc/os-release")
fi
# CHROOT supported?
STATUS=$(type -p stat)
if [[ "${STATUS}" ]]; then
	if [[ "${ISROOT}" ]]; then
		ASROOT=$(stat -c %d:%i /proc/1/root/.)
	fi
	if [ "$(stat -c %d:%i /)" != "${ASROOT}" ]; then
		ISCHROOT="Yes"
	else
		ISCHROOT=""
	fi
fi

# Terminal Detection & color
case "${TERM}" in
	"dumb");;
	*)
		COLUMNZ=$(tput cols)
		TXTRED=$(tput setaf 1)
		TXTBLD=$(tput bold)			 # Bold
		TXTGRN=${TXTBLD}$(tput setaf 2) # bold green
		BLDBLU=${TXTBLD}$(tput setaf 4) # blue
		BLDWHT=${TXTBLD}$(tput setaf 7) # white
		YELLOW=$(tput setaf 3)			# yellow
		TXTRST=$(tput sgr0)			 # Reset
		INFO="${BLDWHT}"				# Feedback
		PASS="${BLDWHT}"*"${TXTRST}"
		WARNING="${TXTBLD}${YELLOW}"
		QUES="${BLDWHT}"?"${TXTRST}"
		BRIGHT=$(tput bold);;
esac

# Debug?
DEBUG=$(echo "$*" | grep -i "debug")

DATECURRENT=$(date +"%Y%m%d")
IPERF=$(type -p iperf3)

# Optional Network Data
ETHTOOL=$(type -p ethtool)

# Get Directory executed in.
CURRENT="${PWD}"

# check to see if notify is installed & if sound is supported.
NOTIFY=$(type -p notify-send)
SOUND=$(type -p canberra-gtk-play)

#Pull info we will use to compare against later
IUSER=${SUDO_USER:-$USER}
IHOME="/home/${IUSER}"

# Timer Declarations
declare -a STARTSECS=();
declare -a STOPSECS=();
#declare -a STARTS=();
#declare -a STOPS=();
declare -a OBJECT=();
declare -i TINDEX;

# DISK Operations? - Taking a stab at calculating disk / file sizes smartly up to Yottabyte
# Could easily roll up to a Geopbyte.
# · 1 Bit = Binary Digit
# · 8 Bits = 1 Byte
# · 1024 Bytes = 1 Kilobyte
# · 1024 Kilobytes = 1 Megabyte
# · 1024 Megabytes = 1 Gigabyte
# · 1024 Gigabytes = 1 Terabyte
# · 1024 Terabytes = 1 Petabyte
# · 1024 Petabytes = 1 Exabyte
# · 1024 Exabytes = 1 Zettabyte
# · 1024 Zettabytes = 1 Yottabyte
# · 1024 Yottabytes = 1 Brontobyte
# · 1024 Brontobytes = 1 Geopbyte

# See additional code in function FileSize to see how I did so using the array
# defined below.
declare -a DISKSIZES=("KB" "MB" "GB" "TB" "PB" "EB" "ZB" "YB")

finish () {
	if [[ "${DEBUG}" ]]; then
		echo "APPNAME:${APPNAME} | EUID: ${EUID} | USER: ${USER} | IUSER: ${IUSER} | ROOT: ${TRUEROOT} EXIT CODE: $?"
	fi
	if ! [[ "${SUPPRESS}" ]]; then
		Timer "Stop" "${APPNAME}"
		FullBar
	fi
}

# trap ctrl-c and call ctrl_c()
ctrl_c () {
		echo -en "\033[1G"
		echo -en "\033[1A\033[2K"
		Error "** Trapped CTRL-C, exiting."
		FullBar
		shopt -s extglob
		if [[ "${PWD}" == "/var/cache/apt/archives" ]]; then
			Encapsulate "Flushing bad package(s).  Please allow this to complete."
			find . -mindepth 1 ! -type d -regex 'partial\(/.*\)?' -delete
			rm "*.txt" 2>/dev/null
			if [[ -d ".debs/" ]]; then
				rm -R .debs/
			fi
		fi
		RUNNINGINSTANCES=$(ps -C apt-get | wc -l)
		if [[ "${RUNNINGINSTANCES}" -gt 1 ]]; then
			PID=$(pgrep apt-get)
			#echo "PID: $PID INSTANCES: ${RUNNINGINSTANCES}"
			CROAK=$(sudo killall -9 apt-get 2>/dev/null)
			while [[ -e "/proc/${PID}" ]]
			do
				sleep .6
			done
		fi
		RUNNINGINSTANCES=$(ps -C repostorm | wc -l)
		if [[ "${RUNNINGINSTANCES}" -gt 1 ]]; then
			PID=$(pgrep repostorm)
			#echo "PID: $PID INSTANCES: ${RUNNINGINSTANCES}"
			CROAK=$(sudo killall -9 repostorm 2>/dev/null)
			while [[ -e "/proc/${PID}" ]]
			do
				sleep .6
			done
		fi
		RUNNINGINSTANCES=$(ps -C uetheme | wc -l)
		if [[ "${RUNNINGINSTANCES}" -gt 1 ]]; then
			PID=$(pgrep uetheme)
			#echo "PID: $PID INSTANCES: ${RUNNINGINSTANCES}"
			SUPPRESS=$(sudo killall -9 uetheme 2>/dev/null)
			while [[ -e "/proc/${PID}" ]]
			do
				sleep .6
			done
		fi
		if [[ "${DEBUG}" ]]; then
			echo "DEBUG: ${PWD}"
		fi
		if [[ "${ISARCH}" ]]; then
			if [[ -w "/var/cache/apt/archives/lock" ]]; then
				Encapsulate "${PROGNAME}: Cleaning packages."
				FullBar
				pacman -Sc
				FullBar
			fi
		else
			if [[ -w "/var/cache/apt/archives/lock" ]]; then
				Encapsulate "${PROGNAME}: Cleaning packages."
				FullBar
				apt-get clean
				apt-get autoclean
				FullBar
			fi
		fi
		exit 1;
}

# Dynamically display terminal window size
RedrawTerm () {
	clear
	if [[ "${DEBUG}" ]]; then
		echo "Width = $(tput cols) Height = $(tput lines)"
	fi
	COLUMNZ=$(tput cols)
}

trap RedrawTerm WINCH
trap ctrl_c INT
trap finish EXIT

Thousands () {
	FORMATTED=$(echo "${1}" | sed -r ':L;s=\b([0-9]+)([0-9]{3})\b=\1,\2=g;t L')
}

Extension () {
	if [[ -f "${1}" ]]; then
		EXTENSION="${1##*.}"
		FILENAME="${1%.*}"
	fi
}

calc_disk() {
	local total_size=0
	local array=$@
	for size in ${array[@]}
	do
		[ "${size}" == "0" ] && size_t=0 || size_t=`echo ${size:0:${#size}-1}`
		[ "`echo ${size:(-1)}`" == "K" ] && size=0
		[ "`echo ${size:(-1)}`" == "M" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' / 1024}' )
		[ "`echo ${size:(-1)}`" == "T" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' * 1024}' )
		[ "`echo ${size:(-1)}`" == "G" ] && size=${size_t}
		total_size=$( awk 'BEGIN{printf "%.1f", '$total_size' + '$size'}' )
	done
	echo ${total_size}
}

FileSize () {
	if [[ "${1}" == "-d" ]]; then
		DIR="${2}"
		FTP=""
	else
		FTP="${1}"
	fi
	if [[ -f "${FTP}" ]]; then
		TOTALSIZE=$(stat -c%s "${FTP}")
		Thousands "${TOTALSIZE}"
		KBS=$(echo "scale=2;${TOTALSIZE%/*}/1024"|bc)
		SIZE="${TOTALSIZE}"
		for XX in "${DISKSIZES[@]}"
		do
			SIZE=$(echo "scale=2;${SIZE%/*}/1024"|bc)
			# Dump the decimal just to see if we have hit the 1024 or less mark.
			KBS=$(echo "${SIZE}" | cut -d . -f1)
			# Debugging:
			echo "TESTINGSIZE: ${KBS} ${XX}"
			if [[ "${KBS}" -lt 1024 && "${KBS}" -gt 1 ]]; then
				TRUESIZE="${KBS}${XX}"
				#echo "${KBS} $XX"
			fi
		done
	else
		if [[ -d "${DIR}" ]]; then
			TOTALSIZE=$(du -s -B1 "${PWD}" | cut -d "/" -f1 | cut -f1)
			Thousands "${TOTALSIZE}"
			KBS=$(echo "scale=2;${TOTALSIZE%/*}/1024"|bc)
			SIZE="${TOTALSIZE}"
			for XX in "${DISKSIZES[@]}"
			do
				SIZE=$(echo "scale=2;${SIZE%/*}/1024"|bc)
				# Dump the decimal just to see if we have hit the 1024 or less mark.
				KBS=$(echo "${SIZE}" | cut -d . -f1)
				# Debugging:
				# echo "TESTINGSIZE: ${KBS} $XX"
				if [[ "${KBS}" -lt 1024 && "${KBS}" -gt 1 ]]; then
					TRUESIZE="${KBS}${XX}"
				else
					TRUESIZE="${KBS}"
					Thousands "${TRUESIZE}"
					#echo "${KBS} $XX"
				fi
			done
		else
			Error "${FTP} does not exist."
		fi
	fi
}

# Usage: Encapsulate
# Encapsulate "Repostorm 1.8.7 is entering extraction mode."
# Example: ▒ Repostorm 1.8.7 is entering extraction mode. ▒
Encapsulate () {
	# Verify a message has been sent to this otherwise do squat.
	# Example: Encapsulate ("Repostorm ${REPOVERSION} is entering extraction mode.")
	# ▒ Repostorm 1.7.7 is entering extraction mode.					   ▒

	STP="${1}"
	if [[ "${STP}" ]]; then
		STRLEN="${#STP}"
		((STRLEN=STRLEN + 3))
		((DISTANCE=COLUMNZ - STRLEN))
		GREPPED=$(echo "${STP}" | grep -E "")
		if [[ "${GREPPED}" ]]; then
			((STRLEN=STRLEN - 13))
		fi
		if ! [[ "${SUPPRESS}" ]]; then
			echo -en "${BRIGHT}${BLDWHT}▒ ${BRIGHT}${TXTGRN}${STP}"
		else
			echo "${STP}"
		fi
		if ! [[ "${SUPPRESS}" ]]; then
			RR=0; while [[ "${RR}" -lt "${DISTANCE}" ]]; do echo -n " "; ((RR=RR+1)); done; echo "${BRIGHT}${BLDWHT}▒";
		fi
	fi
	echo -en "${TXTRST}"
}

# Center data passed to on screen
# Center data passed to on screen
Center () {
	STP="${1}"
	ERRORRPT="${2}"
	if [[ "${STP}" ]]; then
		STRLEN="${#STP}"
		((CENTER=STRLEN / 2 ))
		#CENTER=CENTER-1
		((TCENTER=COLUMNZ / 2 ))
		#TCENTER=TCENTER-1
		((DISTANCE=TCENTER - CENTER))
		((DISTANCE=DISTANCE - 2))
		if ! [[ "${ERRORRPT}" ]]; then
			echo -en ""
		else
			echo -en "${TXTRED}"
		fi
		if ! [[ "${SUPPRESS}" ]]; then
			RR=0; while [[ "${RR}" -lt "${DISTANCE}" ]]; do echo -n "${BRIGHT}${BLDWHT}▒"; ((RR=RR+1)); done;
		fi
		if ! [[ "${ERRORRPT}" ]]; then
			echo -en ""
		else
			echo -en "${TXTRED}"
		fi
		echo -en " ${STP} "
		if ! [[ "${SUPPRESS}" ]]; then
			TT=0; while [ "${TT}" -lt "${DISTANCE}" ]; do echo -n "${BRIGHT}${BLDWHT}▒"; ((TT=TT+1)); done;
		fi
		((CALC=RR + TT + STRLEN + 2))
		if [[ "${CALC}" -lt "${COLUMNZ}" ]]; then
			if ! [[ "${SUPPRESS}" ]]; then
				while [[ "${CALC}" -lt "${COLUMNZ}" ]]; do echo -n "${BRIGHT}${BLDWHT}▒"; ((CALC=CALC+1)); done; echo;
			fi
		fi
	fi
	# echo "STRING LEN: ${STRLEN} CENTER: $CENTER TOTAL CNTER: $TCENTER RR:${RR} TT:${TT} COLUMNZ: ${COLUMNZ} CALC: ${CALC} DISTANCE: ${DISTANCE}"
	echo -en ""
}

# Draws a bar across the screen based on screen size detected (columnz)
FullBar () {
	if ! [[ "${SUPPRESS}" ]]; then
		RR=1; while [[ "${RR}" -le "${COLUMNZ}" ]]; do echo -n "${BRIGHT}${BLDWHT}▒"; ((RR=RR+1)); done; echo;
	fi
}

# for outputting to X-11 screen a notification of completion and playing sound.
# The sound file is from the "Optional" ultimate-edition-sound-theme
Notification () {
	# Is X11 running?
	X="${DISPLAY}"
	DISP=$(printf "[%s]" "${DISPLAY}" "${XAUTHORITY}" | grep ":0")

	#	X=$(xdpyINFO -display :0) >/dev/null
	if [[ "${DEBUG}" ]]; then
		echo "DEBUG: $X"
	fi
	# Does the user have the optional UE Sound scheme installed?
	if [[ -f "/usr/share/sounds/Ultimate Edition Sound Scheme/stereo/itisdone.wav" ]]; then
		WAVE="1"
	fi
	# Is the user in an X11 GUI environment and have notification OSD installed?
	if [[ "${DISP}" && "${NOTIFY}" ]]; then
		INSTALLED=$(type -p notify-send)
		if [[ "${INSTALLED}" ]]; then
			if ! [[ "${SUPPRESS}" ]]; then
				notify-send -u normal -a "${APPNAME}" "${1}" -i /usr/share/ultimate_edition/logo.png -t 5000
			fi
		fi
	fi
	# Does the user have pre-requisites? If so, break out the Cylon voice.
	if [[ "${SOUND}" && "${WAVE}" && "${DISP}" ]]; then
		INSTALLED=$(type -p canberra-gtk-play)
		if [[ "${INSTALLED}" ]]; then
			if ! [[ "${SUPPRESS}" ]]; then
				canberra-gtk-play --file "/usr/share/sounds/Ultimate Edition Sound Scheme/stereo/itisdone.wav" 2>/dev/null &
			fi
		fi
	fi
	# Display message in terminal unconditionally
	if ! [[ "${SUPPRESS}" ]]; then
		Encapsulate "${1}"
	fi
}

# Set a timer to display duration of download (s)
# Usage:  Timer [start|stop]
DownloadTimer () {
	TCMD="${1^^}"
	case "${TCMD}" in
		START) STARTS=$(date +%s)
		;;
		STOP) STOPS=$(date +%s)
			[[ ! "${STARTS}" ]] && Error "[Internal Error] Timer did not record a start time." && return
			(( DSECS=STOPS-STARTS))
			DLAPSE=$(date -u -d@"${DSECS}" +"%-Hh%-Mm%-Ss")
		;;
		*) Error "[Internal Error] Unknown arg ${TCMD}"
		;;
	esac

}

# Download various packages showing progression...
Download () {
	local URL="${1}"
	GREPIT=$(echo "${URL}" | grep -i "http")
	if [[ "${GREPIT}" ]]; then
		FILENAME=$(echo "${URL##*/}")
		if [[ -f "${FILENAME}" ]]; then
			Encapsulate "${FILENAME} exists, deleting for re-download."
			rm "${FILENAME}"
		fi
	else
		GREPIT=$(echo "${URL}" | grep -i "theme")
		if [[ "${GREPIT}" ]]; then
			URL="${THEMEFOLDER}/${1}"
		else
			URL="${ROOTFOLDER}/${1}"
		fi
	fi
	Encapsulate "Downloading: ${URL}"
	Encapsulate "Filename: ${FILENAME}"
	DownloadTimer "Start" "${FILENAME}"
	wget --progress=dot "${URL}" 2>&1 | grep --line-buffered "%" | sed -u -e "s,\.,,g" | awk '{printf("%4s", $2)}'

	echo -ne ""
	DownloadTimer "Stop" "${FILENAME}"
	FileSize "${FILENAME}"
	#echo $?
	Encapsulate "Download complete: ${FILENAME} ${FORMATTED} bytes (${TRUESIZE}). Download time: ${DLAPSE}"
}

# Dump data to the screen in pretty columns.
CColumnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE=151
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "${ARRAY_COUNTER}" -gt 4 ]]; then
				ARGUMENTS[$ARRAY_COUNTER]="${ARG}"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
				# echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
				#echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is $TLEN"
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	#echo "${MAINS}"
	if [[ "${1}" = '-t' ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-36s %-14s %-14s %-14s %-1s" "▒" "${2}" "${3}" "${4}" "${5}" "${6}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-36s %-14s %-14s %-14s %-${MAINS}s %-1s" "▒" "${1}" "${2}" "${3}" "${4}" "${5}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}

# Dump data to the screen in pretty columns.
ControlColumnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE="${#2}"
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "${ARRAY_COUNTER}" -gt 4 ]]; then
				ARGUMENTS[${ARRAY_COUNTER}]="${ARG}"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	if [[ "${DEBUG}" ]]; then
		echo "#: $# VARS: $*"
		LONGESTLENGTH="${#2}"
		echo "Length of ${2} is ${LONGESTLENGTH}"
		echo ${COLUMNZ}
		echo "${MAINS}"
		echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
		echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is ${TLEN}"
	fi
	if [[ "${1}" = '-t' ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-14s %-7s %-11s %-8s %-8s %-1s" "▒" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-14s %-7s %-11s %-8s %-8s %-${MAINS}s %-1s" "▒" "${1}" "${2}" "${3}" "${4}" "${5}" "${6}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}
# Dump data to the screen in pretty columns.
Columnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE=151
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "$ARRAY_COUNTER" -gt 4 ]]; then
				ARGUMENTS[$ARRAY_COUNTER]="$ARG"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
				# echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
				#echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is $TLEN"
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	#echo "${MAINS}"
	if [[ "${1}" = '-t' ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-60s %-14s %-56s %-13s %-1s" "▒" "${2}" "${3}" "${4}" "${5}" "${6}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-60s %-14s %-56s %-13s %-${MAINS}s %-1s" "▒" "${1}" "${2}" "${3}" "${4}" "${5}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}

# Dump data to the screen in pretty columns.
EColumnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE=151
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "$ARRAY_COUNTER" -gt 4 ]]; then
				ARGUMENTS[$ARRAY_COUNTER]="$ARG"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
				# echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
				#echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is $TLEN"
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	#echo "${MAINS}"
	LONGESTFILENAME=$(find . | awk 'function base(f){sub(".*/", "", f); return f;} {print length(base($0))}'| sort -nr | head -1)
	(( LONGESTFILENAME = LONGESTFILENAME + 2)) # Allow for space before and after and the /
	if [[ "${1}" == "-t" ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-${LONGESTFILENAME}s %-12s %-12s %-12s %-1s" "▒" "${BLDBLU}${2}" "${TXTRED}${3}" "${YELLOW}${4}" "${BLDWHT}${5}" "${6}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-${LONGESTFILENAME}s %-13s %-15s %-15s %-${MAINS}s %-1s" "▒" "${BLDBLU}${1}" "${TXTRED}${2}" "${YELLOW}${3}" "${BLDWHT}${4}" "${5}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}

# Dump data to the screen in pretty columns for folders.
FColumnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE=151
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "$ARRAY_COUNTER" -gt 4 ]]; then
				ARGUMENTS[$ARRAY_COUNTER]="$ARG"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
				# echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
				#echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is $TLEN"
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	#echo "${MAINS}"
	LONGESTFILENAME=$(find . -mindepth 1 -maxdepth 1 -type d | awk 'function base(f){sub(".*/", "", f); return f;} {print length(base($0))}'| sort -nr | head -1)
	(( LONGESTFILENAME = LONGESTFILENAME + 10)) # Allow for space before and after.
	if [[ "${1}" == "-t" ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-${LONGESTFILENAME}s %-13s %-15s %-15s %-1s" "▒" "${BLDBLU}${2}" "${TXTRED}${3}" "${YELLOW}${4}" "${BLDWHT}${5}" "${6}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-${LONGESTFILENAME}s %-13s %-15s %-15s %-${MAINS}s %-1s" "▒" "${BLDBLU}${1}" "${TXTRED}${2}" "${YELLOW}${3}" "${BLDWHT}${4}" "${5}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}

TColumnize() {
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		#echo -e "${bldgrn}Number of switches passed: $#"
		for ARG in "$@"
		do
			array_counter=$((array_counter + 1))
			if [[ "$array_counter" -gt 2 ]]; then
				#echo "Switch $array_counter: $ARG"
				ARGUMENTS[$array_counter]="$ARG"
				tLen="${#ARGUMENTS[$array_counter]}"
				if [[ $tLen -ge $WIDEST ]]; then
					WIDEST="$tLen"
				fi
				#echo "Length of ${ARGUMENTS[$array_counter]} is $tLen"
			fi
			#echo "The widest passed varible is $WIDEST"
		done
	else
		#echo -e "${bldgrn}Number of switches passed: $#"
		for ARG in "$@"
		do
			array_counter=$((array_counter + 1))
			if [[ "$array_counter" -gt 1 ]]; then
				#echo "Switch $array_counter: $ARG"
				ARGUMENTS[$array_counter]="$ARG"
				tLen="${#ARGUMENTS[$array_counter]}"
				if [[ "$tLen" -ge "$WIDEST" ]]; then
					WIDEST="$tLen"
				fi
				#echo "Length of ${ARGUMENTS[$array_counter]} is $tLen"
			fi
			#echo "The widest passed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	MAINS=$(echo "scale=2; ${COLUMNZ}-30" | bc)
	MAINS=${MAINS%.*}
	#echo $MAINS
	MAINS=$((MAINS - 2))
	MAINS=$((MAINS / 4))
	#echo $MAINS
	if [[ "${1}" = '-t' ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-26s %-8s %-16s %-5s %-3s %-13s %-16s %-16s %-1s\n" "▒" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}" "${8}" "${9}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-26s %-8s %-16s %-5s %-3s %-13s %-16s %-16s %-1s\n" "▒" "${1}" "${2}" "${3}" "${4}" "${5}" "${6}" "${7}" "${8}" "${9}"
	fi
}

# Dump data to the screen in pretty columns.
CColumnize () {
	declare -i USEDSPACE
	USEDSPACE=0
	ARRAY_COUNTER=0
	TLEN=0
	# Columnize is an internally called function exclusively.
	# EXAMPLE
	# -t to shove through the column titles we will count the number of switches and
	# calculate spacing eventually.
	if [[ "${1}" == "-t" ]]; then
		USEDSPACE=151
	else
		#echo -e "${bldgrn}Number of switches PASSed: $#"
		for ARG in "$@"
		do
			ARRAY_COUNTER=$((ARRAY_COUNTER + 1))
			if [[ "$ARRAY_COUNTER" -gt 4 ]]; then
				ARGUMENTS[$ARRAY_COUNTER]="$ARG"
				TLEN="${#ARGUMENTS[$ARRAY_COUNTER]}"
				USEDSPACE=149
				USEDSPACE=$((USEDSPACE + "${TLEN}"))
				# echo "Switch $ARRAY_COUNTER: $ARG (${TLEN}) | USEDSPACE:${USEDSPACE}"
				#echo "Length of ${ARGUMENTS[$ARRAY_COUNTER]} is $TLEN"
			fi
			#echo "The widest PASSed varible is $WIDEST"
		done
	fi
	#echo "#: $# VARS: $*"
	#LONGESTLENGTH="${#2}"
	#echo "Length of ${2} is $LONGESTLENGTH"
	#echo ${COLUMNZ}
	#echo "${MAINS}"
	if [[ "${ISROOT}" ]]; then
		LONGESTFILENAME=$(find . | awk 'function base(f){sub(".*/", "", f); return f;} {print length(base($0))}'| sort -nr | head -1)
	else
		LONGESTFILENAME=16
	fi
	(( LONGESTFILENAME = LONGESTFILENAME + 5)) # Allow for space before and after.
	if [[ "${1}" == "-t" ]]; then
		#"#" "DEV" "VENDOR" "LABEL" "TYPE" "SIZE"
		printf "%-0s %-${LONGESTFILENAME}s %-12s %-12s %-12s %-1s" "▒" "${2}" "${3}" "${4}" "${5}" "${6}"
	else
		#MAINS=$(expr $MAINS / 2)
		printf "%-0s %-${LONGESTFILENAME}s %-13s %-15s %-15s %-${MAINS}s %-1s" "▒" "${1}" "${2}" "${3}" "${4}" "${5}"
	fi
	echo -e "\033[${COLUMNZ}G▒"
}

Error () {
	Center "${1}" "--ERROR"
}

# Usage: Eye Candy "Message"
# Example: Eye Candy "Repostorm ${REPOVERSION} is entering extraction mode."
# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
# ▒ Repostorm 1.7.7 is entering extraction mode. ▒
# ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
EyeCandy () {
	# Verify a message has been sent to this otherwise do squat.

	STP="${1}"
	if [[ "${STP}" ]]; then
		STRLEN="${#STP}"
		((STRLEN=STRLEN + 3))
		GREPPED=$(echo "${STP}" | grep -E "")
		if [[ "${GREPPED}" ]]; then
			((STRLEN=STRLEN - 13))
		fi
		if ! [[ "${SUPPRESS}" ]]; then
			RR=0; while [[ "${RR}" -le "${STRLEN}" ]]; do echo -n "▒"; ((RR=RR+1)); done; echo;
		fi
		echo -e "${BLDWHT}▒${TXTGRN} ${STP} ${BLDWHT}▒"
		if ! [[ "${SUPPRESS}" ]]; then
			RR=0; while [[ "${RR}" -le "${STRLEN}" ]]; do echo -n "▒"; ((RR=RR+1)); done; echo;
		fi
	fi
	echo -en "${TXTRST}"
}

# Set a timer to display duration ##
# Usage:  Timer <[start|stop]> <OBJECT>
Timer () {
	# Debugging switches... Uncomment to see output: 03/30/2016 added as an
	# Optional switch - useful for me and the end user.
	# Internal function Sample: Timer "Start" "Downloading Files"
	# Download "Blah, blah, ..."
	# Timer "Stop" "Downloading Files"
	# Results: Timer Complete Downloading Files: 0h0m40s
	# With function FileSize:
	# Downloaded: 178 files a total of 13,741,490,176 bytes (12GB) in 0h0m40s
	if [[ "${DEBUG}" ]]; then
		shopt -s expand_aliases
		# shellcheck disable=SC2128
		Center "DEBUG INFORMATION: ${FUNCNAME}"
		# a bug has been filed against shellcheck: https://github.com/koalaman/shellcheck/issues/634
		echo -en "Caller: "
		caller
	fi
	if [[ "${2}" ]]; then
		OBJECT[${TINDEX}]="${2}"
	fi
	TCMD="${1^^}"

	case "${TCMD}" in
		START) STARTSECS[${TINDEX}]=$(date +%s)
				if [[ "${OBJECT[${TINDEX}]}" ]]; then
					if [[ "${2}" != "${APPNAME^}" ]]; then
						if ! [[ "${SUPPRESS}" ]]; then
							Encapsulate "Timer Started: ${OBJECT[${TINDEX}]}"
						fi
					fi
				fi
				(( TINDEX + 1 ))
		;;
		STOP) 	CINDEX=0
				for EACH in "${OBJECT[@]}"
				do
					if [[ "${EACH}" == "${2}" ]]; then
						FINDEX="${CINDEX}"
					fi
					(( CINDEX + 1 ))
				done
				STOPSECS[${FINDEX}]=$(date +%s)
				[[ ! "${STARTSECS[${FINDEX}]}" ]] && return
				(( DIFFSECS=STOPSECS[${FINDEX}]-STARTSECS[${FINDEX}] ))
				TIMELAPSE=$(date -u -d@"${DIFFSECS}" +"%-Hh%-Mm%-Ss")
				if [[ "${OBJECT[${FINDEX}]}" ]]; then
					if ! [[ "${SUPPRESS}" ]]; then
						Encapsulate "Timer Complete ${OBJECT[$FINDEX]}: ${TIMELAPSE}"
					fi
				fi

		;;
		*) Error "[Internal Error] ${FUNCNAME}: Unknown arg ${TCMD}"
	esac
	TTIMEM="${TIMELAPSE}"
}

FormatNUM () {
	INPUTNUM="${1}"
	if [[ "${INPUTNUM}" ]]; then
		OUTPUTNUM=$(echo "${INPUTNUM}" | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta')
	fi
}

# Dump version information and exit function
VersionDump () {
	# Debugging switches... Uncomment to see output: 03/30/2016 added as an
	# Optional switch - useful for me and the end user.
	AMOUNT=0
	if [[ "${DEBUG}" ]]; then
		Center "DEBUG INFORMATION: ${FUNCNAME[1]}"
		for EACH in "$@"
		do
			((AMOUNT ++))
			echo "$AMOUNT:${EACH} "
		done
		echo -e -n "Caller [LINE] / APP: "
		caller
		FullBar
		echo -e -n "${TXTRST}"
	fi
	if ! [[ "${SUPPRESS}" ]]; then
		Center "${APPNAME} (${PROGNAME}) ${VERSION}, ${BUILDDATE}"
		Encapsulate "GNU ${PROGNAME} home page: <https://${WEBSITE}/>."
		Encapsulate "E-mail bug reports to: ${EMAIL}."
		Encapsulate "Be sure to include the word ${PROGNAME} somewhere in the Subject: field."
		FullBar
	fi
}

CheckRoot () {
	if [[ "${EUID}" -ne 0 ]]; then
		Error "Please run as root or sudo privilages."
		exit 1;
	else
		ISROOT=true
	fi
}

Spinner () {
	local DATA="${1}"
	local PID="$!"
	local DELAY=0.1
	local SPINSTR='|/-\'
	declare -i CHARS
	while kill -0 "${PID}" 2> /dev/null; do
		local TEMP="${SPINSTR#?}"
		printf "${BRIGHT}${BLDWHT}▒ ${BRIGHT}${TXTGRN}[%c] ${DATA}" "${SPINSTR}"
		local SPINSTR="${TEMP}${SPINSTR%"${TEMP}"}"
		sleep "${DELAY}"
		local RESET="\b\b\b\b\b\b\b\b\b"
		local CHARS=$(echo "${DATA}" | wc -c)
		for (( I=0; I<${#DATA}; I++ ))
		do
			RESET+="\b"
		done
		printf "${RESET}"
	done
	printf "	\b\b\b\b\b\b\b\b"
}

# Text formatting in a pretty style based on the size of the users screen real estate.
FormatText () {
	shopt -u nullglob
	declare -a STP=();
	TTF="${1}"
	DTP=$(printf %s\\n "${TTF}")
	AVAILWIDTH=$(("${COLUMNZ}" -4))
	# echo "WIDTH: ${AVAILWIDTH}"
	OIFS=$IFS
	IFS=$'\n'
	STP=$(echo "${DTP}" | fmt -s -u -w "${AVAILWIDTH}")
	STP=(${STP})
	#IFS=$'\n'
	#printf '%s\n' "${text[*]}" | fmt -w 45
	#STP=$(echo "${TTF}" | fmt -u -w "${AVAILWIDTH}")
	for EACH in "${STP[@]}"
	do
		Encapsulate "${EACH}"
	done
	IFS=$OIFS
}

# Only to be used when something you are writing takes a very long time to complete
# Data is the title of what is being processed. Percent is the percentage complete.
# Example: ProgressBar "50.1" "Processing ISO 366 of 730"
# the software calculates the length of the strings being processed & adjusts.
# Acuracy is not necessary here. We are bot going to wastefully call on tools for percision.
ProgressBar ()  {
	local DATA
	local PERCENT
	DATA="${2}"
	PERCENT="${1%.*}"
	DLEN="${#DATA}"
	c=$(( "${COLUMNZ}"-"${DLEN}"-${#PERCENT}-7 ))
	j=$((${PERCENT}*c/100))
	tput sc
	printf "▒ ${DATA}: ${PERCENT}%% $(for((k=0;k<j;k++));do printf "▒";done;)"
	tput cuf $((c-j))
	printf "▒"
	tput rc;
}

BigBarFiles ()  {
	local DATA
	local PERCENT
	LONGESTFILENAME=$(find . -maxdepth 1 -type f -iname "*.deb" | awk 'function base(f){sub(".*/", "", f); return f;} {print length(base($0))}'| sort -nr | head -1)
	(( LONGESTFILENAME = LONGESTFILENAME + 2 + ${#CDATA} )) # Allow for space before and after.
	DATA="${2}"
	PERCENT="${1%.*}"
	CDATA="${3}"
	M="${4}"
	LOV="${5}"
	DLEN="${#DATA}"
	c=$(( "${COLUMNZ}" - "${LONGESTFILENAME}" - 3 - ${#CDATA} - 6 ))
	j=$((${PERCENT}*c/100))
	tput sc
	printf "%-0s %-${LONGESTFILENAME}s %-${#CDATA}s %-3s %-${J}s %-1s" "▒" "${DATA}" "${M}"  "${PERCENT}% $(for((k=0;k<j;k++));do printf "▒";done;)"
	# ;tput cuu1;tput el;
	tput cuf $((${COLUMNZ}))
	printf "▒"
	tput rc;
}

BigBarFolders ()  {
	shopt -s dotglob
	shopt -s nullglob
	local DATA
	local PERCENT
	DATA="${2}"
	LFN="${1}"
	PERCENT="${5%.*}"
	CDATA="${3}"
	PROG="${4}"
	DLEN="${#DATA}"
	c=$(( "${COLUMNZ}" - "${LFN}" - 3 - ${CDATA} - 6 ))
	j=$((${PERCENT}*c/100))
	tput sc
	printf "%-0s %-${LFN}s %-${CDATA}s %-3s %-${J}s %-1s" "▒" "${DATA}" "${PROG}" "${PERCENT}% $(for((k=0;k<j;k++));do printf "▒";done;)"
	# ;tput cuu1;tput el;
	tput cuf $((${COLUMNZ}))
	printf "▒"
	tput rc;
}

PromptYN () {
	YN=""
	if ! [[ "${PROMPTSUPPRESSION}" ]]; then
	while true; do
		echo -en "▒ ${1}"
		read YN
		YN=${YN:-Y}
		echo -en "\033[1A\033[2K"
		case "${YN}" in
			[Nn]* ) return 1;;
			[Yy]* ) return 0;
					break;;
				* ) Encapsulate "Please answer [y] or n.";;
		esac
	done
	fi
}

# TMOSB Specific
# Try to think of the below as a basic database where the values coincide
# Example when it detects 14.10 the arrays will be cycled through looking for
# the value of 14.10 as the UEARRAY would be value[16] the value of
# [16] of DISTARRAY would be Trusty Tahr
#DISTSSUPPORTED=48
declare -i DISTSSUPPORTED;
declare -a ISLTS=( "4.2" "4.3" "5.0" "5.1" "5.8" "5.9" "6.6" "6.7" "7.4" "7.5" "8.4" "8.5" "12.04" "14.04" "16.04" "18.04" "20.04" "22.04" "24.04");
declare -a OSARRAY=( 'quantal' 'quantal' 'raring' 'raring' 'saucy' 'saucy' 'trusty' 'trusty' 'utopic' 'utopic' 'vivid' 'vivid' 'wily' 'wily' 'xenial' 'xenial' 'yakkety' 'yakkety' 'zesty' 'zesty' 'artful' 'artful' 'bionic' 'bionic' 'cosmic' 'cosmic' 'disco' 'disco' 'eoan' 'eoan' 'focal' 'focal' 'groovy' 'groovy' 'hirsute' 'hirsute' 'impish' 'impish' 'jammy' 'jammy' 'quantal' 'quantal' 'raring' 'raring' 'saucy' 'saucy' 'trusty' 'trusty' 'utopic' 'utopic' 'vivid' 'vivid' 'wily' 'wily' 'xenial' 'xenial' 'yakkety' 'yakkety' 'zesty' 'zesty' 'artful' 'artful' 'bionic' 'bionic' 'cosmic' 'cosmic' 'disco' 'disco' 'eoan' 'eoan' 'focal' 'focal' 'groovy' 'groovy' 'hirsute' 'hirsute' 'impish' 'impish' 'jammy' 'jammy' 'kinetic' 'kinetic' 'lunar' 'lunar' 'mantic' 'mantic' 'noble' 'noble' 'oracular' 'oracular' );
declare -a UEARRAY=( "3.6" "3.7" "3.8" "3.9" "4.0" "4.1" "4.2" "4.3" "4.4" "4.5" "4.6" "4.7" "4.8" "4.9" "5.0" "5.1" "5.2" "5.3" "5.4" "5.5" "5.6" "5.7" "5.8" "5.9" "6.0" "6.1" "6.2" "6.3" "6.4" "6.5" "6.6" "6.7" "6.8" "6.9" "7.0" "7.1" "7.2" "7.3" "7.4" "7.5" "7.6" "7.7" "7.8" "7.9" "8.0" "8.1" "8.2" "8.3" "8.4" "8.5" "8.6" "8.7" '12.10' '13.04' '13.10' '14.04' '14.10' '15.04' '15.10' '16.04' '16.10' '17.04' '17.10' '18.04' '18.10' '19.04' '19.10' '20.04' '20.10' '21.04' '22.04');
DISTSSUPPORTED="${#UEARRAY[@]}"
NEWESTUE="${UEARRAY[${DISTSSUPPORTED}/3*2-1]}"
#declare -a DEBIAN=("7.6" "7.7" "7.8" "7.9" "7.10" "7.11");
declare -a DISTARRAY=( "Quantal Quetzal" "Quantal Quetzal" "Raring Ringtail" "Raring Ringtail" "Saucy Salamander" "Saucy Salamander" "Trusty Tahr" "Trusty Tahr" "Utopic Unicorn" "Utopic Unicorn" "Vivid Vervet" "Vivid Vervet" "Wily Werewolf" "Wily Werewolf" "Xenial Xerus" "Xenial Xerus" "Yakkety Yak" "Yakkety Yak" "Zesty Zapus" "Zesty Zapus" "Artful Aardvark" "Artful Aardvark" "Bionic Beaver" "Bionic Beaver" "Cosmic Cuttlefish" "Cosmic Cuttlefish" "Disco Dingo" "Disco Dingo" "Eoan Ermine" "Eoan Ermine" "Focal Fossa" "Focal Fossa" "Groovy Gorilla" "Groovy Gorilla" "Hirsute Hippo" "Hirsute Hippo" "Impish Indri" "Impish Indri" "Jammy Jellyfish" "Jammy Jellyfish" "Quantal Quetzal" "Raring Ringtail" "Saucy Salamander" "Trusty Tahr" "Utopic Unicorn" "Vivid Vervet" "Wily Werewolf" "Xenial Xerus" "Yakkety Yak" "Zesty Zapus" "Artful Aardvark" "Bionic Beaver" "Cosmic Cuttlefish" "Disco Dingo" "Eoan Ermine" "Focal Fossa" "Groovy Gorilla" "Hirsute Hippo" "Impish Indri" "Jammy Jellyfish" "Kinetic Kudu" "Lunar Lobster" "Mantic Minotaur" "Noble Numbat" "Oracular Oriole" );
declare -a UBUNTU=( '12.10' '13.04' '13.10' '14.04' '14.10' '15.04' '15.10' '16.04' '16.10' '17.04' '17.10' '18.04' '18.10' '19.04' '19.10' '20.04' '20.10' '21.04' '22.04' '22.10' '23.04' '24.04' '24.10' );
declare -a DEBIAN=( "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" "16" );
declare -a DEBIANARRAY=( "Buzz" "Rex" "Bo" "Hamm" "Slink" "Potato" "Woody" "Sarge" "Etch" "Lenny" "Squeeze" "Wheezy" "Jessie" "Stretch" "Buster" "Bullseye" );
#UETYPE=5
#declare -a UETYPES=("lite" "gamers" "server" "minimal-server");
#declare -a DEBS=("lite" "gamers" "server" "minimal-server" "standard" "full");
#declare -a DEBIAN=("7.6" "7.7");
#UETYPE=5
declare -a UETYPES=( "lite" "gamers" "server" "minimal-server" "developer" "full" );
declare -a DEBS=( "lite" "gamers" "server" "minimal-server" "standard" "full" "developer" "hacking" );
#declare -a DEBIAN=("7.6" "7.7" "7.8" "7.9" "7.10" "7.11");
declare -a UEARCH=( "x64" "x86" "amd64" "i386" "armel" "armhf" "powerpc" "powerpc-smp" "ppc64el" );
declare -a OLDRELEASES=( "2.6" "2.7" "3.4" "3.5" );
declare -a DISTBASE=( "Ultimate Edition" "Ubuntu" "Debian" );
declare -a CYCLE=( "x86" "x64" "armel" "armhf" "powerpc" "powerpc-smp" "ppc64el" );
declare -a EXTRADE=( "xfce" "mate" "kde" "trinity" "lxde" "awesome" "gnome" "lxqt" "unity" "cinnamon" "budgie" "enlightenment" "pantheon" "deepin" );
#declare -i CVER;
#declare -i CSIZE;
declare -a APPLICATIONS=( 'tmosb' 'uecorebuilder' 'uesplash-builder' 'tmgrub' 'internal' );
declare -a APPSRC=( '/bin' '/bin' '/bin' '/usr/share/ultimate_edition' '/usr/share/ultimate_edition' );
declare -a ARGUMENTS=();
#declare -a ARGLENGTH=();
declare -a LOGFILEZ=( "bootstrap.log" "history.log" "dpkg.log" );
declare -a MOUNTPOINTS=( "proc/" "sys/" "dev/");
declare -a UEONLY=( "3.6" "3.7" "3.8" "3.9" "4.0" "4.1" "4.2" "4.3" "4.4" "4.5" "4.6" "4.7" "4.8" "4.9" "5.0" "5.1" "5.2" "5.3" "5.4" "5.5" "5.6" "5.7" "5.8" "5.9" "6.0" "6.1" "6.2" "6.3" "6.4" "6.5" "6.6" "6.7" "6.8" "6.9" "7.0" "7.1" "7.2" "7.3" "7.4" "7.5" );
declare -a UEDISTARRAY=( "Quantal Quetzal" "Quantal Quetzal" "Raring Ringtail" "Raring Ringtail" "Saucy Salamander" "Saucy Salamander" "Trusty Tahr" "Trusty Tahr" "Utopic Unicorn" "Utopic Unicorn" "Vivid Vervet" "Vivid Vervet" "Wily Werewolf" "Wily Werewolf" "Xenial Xerus" "Xenial Xerus" "Yakkety Yak" "Yakkety Yak" "Zesty Zapus" "Zesty Zapus" "Artful Aardvark" "Artful Aardvark" "Bionic Beaver" "Bionic Beaver" "Cosmic Cuttlefish" "Cosmic Cuttlefish" "Disco Dingo" "Disco Dingo" "Eoan Ermine" "Eoan Ermine" "Focal Fossa" "Focal Fossa" "Groovy Gorilla" "Hirsute Hippo" "Impish Indri" "Jammy Jellyfish" );
declare -a EXTRADE=( "XFCE" "MATE" "KDE" "LXDE" "AWESOME" "GNOME" "LXQT" "UNITY" "CINNAMON" "BUDGIE" "ENLIGHTENMENT" "DEEPIN" );
#declare -a DELOCATIONS=(".xfce" ".config/mate" ".kde" ".lxde" ".awesome" ".gnome" ".LX" ".unity" ".cinnamon");
declare -a SERVEROPTIONS=( "sql" "ftp" "wordpress" "apache" "php" "awstats" "monitor" );
declare -a SERVERPACKAGES=( "mysql-server" "vsftpd" "wordpress" "lamp-server^" "awstats, libgeo-ipfree-perl, libnet-ip-perl" "vnstat, htop, bmon, nload, iftop, iptraf, nethogs, slurm, tcptrack, cbm, speedometer, ssh" );
declare -a DES=( "kde" "xfce" "mate" "gnome" "pantheon" "cinnamon" "budgie" "deepin" "cutefish" "enlightenment" "lxde" "lxqt" );
declare -a EXTRAS=( "network" "extra" "installer" "drivers" "hack" "hacking" "security" "ps4" "theemahn" "3d" "themes" "games" "threadripper" );
declare -a EDEFAULTS=( "false" "false" "true" "false" "false" "false" "false" "false" "false" );
declare -a OSTYPES=( "developer" "hacking" "gamers" "lite" "server" "full" "minimal" "steamdeck" "ps4" "wiki" );
declare -a SESSION=( "plasma" "xfce" "mate" "gnome" "pantheon" "cinnamon" "budgie-desktop" "deepin" "cutefish" "enlightenment" "LXDE" "lxqt" );
declare -a DISTOPTIONS=( "stable" "edge" );
declare -a INSTALLDE=( "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "false" "true" "true" );
declare -a GINFO=( "# Ultimate Arch Linux GUI KDE Plasma" "# Ultimate Arch Linux GUI XFCE" "# Ultimate Arch Linux GUI MATE" "# Ultimate Arch Linux GUI Gnome" "# Ultimate Arch Linux GUI Pantheon" "# Ultimate Arch Linux GUI Cinnamon" "# Ultimate Arch Linux GUI Budgie" "# Ultimate Arch Linux GUI Deepin" "# Ultimate Arch Linux GUI Cutefish" "# Ultimate Arch Linux GUI Enlightenment" "# Ultimate Arch Linux GUI LXDE" "# Ultimate Arch Linux GUI LXQT" "# Ultimate Arch Linux Network" "# Ultimate Arch Linux Extra" "# Ultimate Installer" "# Ultimate Edition Drivers" "# Ultimate Edition Hacking" "# Ultimate Edition Security" "# Ultimate Edition TheeMahn" "# Ultimate Edition 3d" "# Ultimate Edition Themes" "# Ultimate Edition Games" "# ThreadRipper" );
declare -a ECOSYSTEM=( "AMD" "INTEL" "NVIDIA" );
# PRE-DETERMINE user selection
GAMERS=$(echo "$*" | grep -i "gamers")
SERVER=$(echo "$*" | grep -i "server")
MSERVER=$(echo "$*" | grep -i "minimal")
LITE=$(echo "$*" | grep -i "lite")
DEVELOPER=$(echo "$*" | grep -i "developer")
if [[ "${GAMERS}" ]]; then
	DEBTYPE="gamers"
	DTYPE="gamers"
fi
if [[ "${SERVER}" ]]; then
	DEBTYPE="server"
	DTYPE="server"
fi
if [[ "${MSERVER}" ]]; then
	DEBTYPE="minimal-server"
	DTYPE="minimal-server"
fi
if [[ "${LITE}" ]]; then
	DEBTYPE="lite"
	DTYPE="lite"
fi
if [[ "${DEVELOPER}" ]]; then
	DEBTYPE="developer"
	DTYPE="developer"
fi
if [[ "${MSERVER}" ]]; then
	SERVER=""
	DTYPE="Minimal-Server"
	DE="NONE"
fi

NetInfo () {
	#Advance network detection to perfection scan all interfaces:
	declare -a IPS=();
	shopt -s dotglob
	shopt -s nullglob
	IPS=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1')
	SAVEIFS=$IFS
	# Change IFS to new line.
	IFS=$'\n'
	IPS=($IPS)
	IFS="$SAVEIFS"
	declare -a INTERFACES=()
	ACTIVE=""
	BYTE=0
	INDEX=-1
	if [[ -d "/sys/class/net/" ]]; then
		ControlColumnize -t "INTERFACE" "STATUS" "SPEED" "DUPLEX" "TYPE" "LOCAL IP"
		FullBar
		CURRENT="${PWD}"
		cd "/sys/class/net/" || exit 1;
		INTERFACES=(*/)
		for EACH in "${INTERFACES[@]}"
		do
			ACT=$(cat "/sys/class/net/${EACH%/}/operstate")
			if [[ "$ACT" == "up" ]]; then
					DEVICE="${EACH%/}"
					#ACTIVE="${EACH%/}"
					DUPLEX=$(ethtool "${DEVICE}" 2>/dev/null | grep -s -i "Duplex" | cut -d ":" -f2 | sed 's/ //g') 2>/dev/null
					ITYPE=$(ethtool "${DEVICE}" 2>/dev/null | grep -s "Port" | cut -d ":" -f2 | cut -d " " -f2) 2>/dev/null
					SPEED=$(ethtool "${DEVICE}" 2>/dev/null | grep -s -i "Speed" | cut -d ":" -f2 | sed 's/ //g') 2>/dev/null
					BYTES=$(ethtool --statistics "${DEVICE}" 2> /dev/null | grep -i "rxq0: rx_bytes:" | cut -d ":" -f3 | sed "s/ //g")
					if [[ "${BYTES}" == "" ]]; then
						if [[ -f "/sys/class/net/${DEVICE}/statistics/rx_bytes" ]]; then
							BYTES=$(cat "/sys/class/net/${DEVICE}/statistics/rx_bytes")
							SPEED=$(ethtool "${DEVICE}" 2>/dev/null | grep -s -i "Speed" | cut -d ":" -f2 | sed 's/ //g') 2>/dev/null
						fi
					fi
					if [[ "${BYTES}" -gt "${BYTE}" ]]; then
						ACTIVE="${EACH%/}"
						BYTE="${BYTES}"
					fi
				if ! [[ "${SPEED}" ]]; then
					SPEED=$(iwconfig ${EACH%/} | grep "Bit Rate=" | cut -d "=" -f2 | cut -d " " -f1,2)
					ITYPE="Wireless"
					DUPLEX=$(iwconfig ${EACH%/} | grep "Frequency:" | cut -d ":" -f2 | cut -d " " -f1,2)
				fi
				INDEX=$(( INDEX + 1 ))
				ControlColumnize "${EACH%/}" "UP" "${SPEED}" "${DUPLEX}" "${ITYPE}" "${IPS[${INDEX}]}"
				#Encapsulate "Interface: ${EACH%/} is $ACT"
			else
				#Encapsulate "Interface: ${EACH%/} is $ACT"
				if [[ "${EACH%/}" != "lo" ]]; then
					ControlColumnize "${EACH%/}" "DOWN" "N/A" "N/A" "N/A" "N/A" "N/A"
				fi
			fi
		done
	else
		Error "No standard interface detected.	Point to Point Protocol?"
	fi
	# Current Seedo work...  If the folder exists most likely it is the
	# active connection set it as such.  Point to Point Protocol evidently
	# does not do states. up / down etc.
	if [[ -d "/sys/class/net/ppp0/" && "${ACTIVE}" == "" ]]; then
		ACTIVE="ppp0"
	fi
	if [[ "${ACTIVE}" ]]; then
		FullBar
		Encapsulate "Active Monitoring Connection:"
		if [[ "${ETHTOOL}" ]]; then
			SPEED=$(ethtool "${ACTIVE}" 2>/dev/null | grep -s -i "Speed" | cut -d ":" -f2 | sed 's/ //g') 2>/dev/null
		fi
		if [[ "${SPEED}" ]]; then
			Encapsulate "${ACTIVE} (Network Speed: ${SPEED})"
		else
			WLIST=$(type -p iwlist)
			if [[ "${WLIST}" ]]; then
				SPEED=$(iwlist "${ACTIVE}" bitrate | grep -i "bit rate" | cut -d "=" -f2)
				Encapsulate "${ACTIVE} (Network Speed: ${SPEED}) Local IP: ${IPS[${INDEX}]}"
			fi
		fi
	else
		Error "No active network interface found."
	fi
	cd "${CURRENT}"
	FullBar
	#Notification "Active networking interface: ${ACTIVE} Speed: ${SPEED}."
	#SetSambaInterface "${ACTIVE}"
	#FullBar
}

SysInfo () {
	# Get System information
	#Get CPU model / info
	BOGOMIPS=$(lscpu | grep -i 'bogomips' | cut -d ":" -f2 | cut -d "=" -f1 | sed "s/ //g")
	RESONATION=$(lscpu | grep -i 'cpu max Mhz' | cut -d ":" -f2 | sed "s/ //g" | cut -d "." -f1)
	if [[ "${UID}" == "0" ]]; then
		CPUMAX=$(dmidecode -t 4 | grep -i "Max Speed:" | cut -d":" -f2)
	fi
	if ! [[ "${RESONATION}" ]]; then
		RESONATION=$(lscpu | grep -i 'CPU MHz' | cut -d ":" -f2 | sed "s/ //g")
	fi
	PROC=$(cat /proc/cpuinfo | grep -m1 'model name' | sed -e 's/.*: //' | uniq)
	if [[ "${CPUMAX}" ]]; then
		Encapsulate "Processor: ${PROC}"
		Encapsulate "Resonating at ${RESONATION} Mhz /${CPUMAX} (Base/Max) (BogoMips: ${BOGOMIPS})"
	else
		if [[ "${BOGOMIPS}" ]]; then
			Encapsulate "Processor: ${PROC}"
			Encapsulate "Resonating at ${RESONATION} Mhz (BogoMips: ${BOGOMIPS})"
		else
			Encapsulate "Processor: ${PROC}"
			Encapsulate "Resonating at ${RESONATION} Mhz"
		fi
	fi
	FullBar
	BOGOMIPS=$(lscpu | grep -i 'bogomips' | cut -d ":" -f2 | cut -d "=" -f1 | sed "s/ //g")
	RESONATION=$(lscpu | grep -i 'cpu max Mhz' | cut -d ":" -f2 | sed "s/ //g" | cut -d "." -f1)
	if [[ "${EUID}" == "0" ]]; then
		CPUMAX=$(dmidecode -t 4 | grep -i "Max Speed:" | cut -d":" -f2)
	fi
	if ! [[ "${RESONATION}" ]]; then
		RESONATION=$(lscpu | grep -i 'CPU MHz' | cut -d ":" -f2 | sed "s/ //g" | cut -d "." -f1)
	fi
	PROC=$(cat /proc/cpuinfo | grep -m1 'model name' | sed -e 's/.*: //' | uniq)
	cname=$( awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
	cores=$( awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo )
	freq=$( awk -F'[ :]' '/cpu MHz/ {print $4;exit}' /proc/cpuinfo )
	ccache=$( awk -F: '/cache size/ {cache=$2} END {print cache}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
	tram=$( LANG=C; free -m | awk '/Mem/ {print $2}' )
	uram=$( LANG=C; free -m | awk '/Mem/ {print $3}' )
	swap=$( LANG=C; free -m | awk '/Swap/ {print $2}' )
	uswap=$( LANG=C; free -m | awk '/Swap/ {print $3}' )
	up=$( awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days, %d hour %d min\n",a,b,c)}' /proc/uptime )
	load=$( LANG=C; w | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
	load=$( LANG=C; uptime | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
	arch=$( uname -m )
	lbit=$( getconf LONG_BIT )
	kern=$( uname -r )
	disk_size1=($( LANG=C df -hPl | grep -wvE '\-|none|tmpfs|devtmpfs|by-uuid|chroot|Filesystem|udev|docker' | awk '{print $2}' ))
	disk_size2=($( LANG=C df -hPl | grep -wvE '\-|none|tmpfs|devtmpfs|by-uuid|chroot|Filesystem|udev|docker' | awk '{print $3}' ))
	disk_total_size=$( calc_disk "${disk_size1[@]}" )
	disk_used_size=$( calc_disk "${disk_size2[@]}" )
}

NVMEInfo () {
	# Set hard-coded variables
	ISHDDTEMP=$(type -p hddtemp)
	ISHDDEXEC="NO"
	SENSORS=$(type -p sensors)
	NF=0
	#NVME Drive(s)?
	awk '/dev\/nvme/ {print $1}' "/etc/mtab" | sort | while read line
	do
		if [[ "$DEBUG" ]]; then
			echo "DEBUGGING: ${line}"
		fi
		(( NF = NF + 1 ))
		NVTEMP=$(sensors -f | grep -a2 'nvme' | grep -m "${NF}" 'Composite:' | cut -d '+' -f2 | cut -d '.' -f1 | tail -n 1)
		MOUNTPOINT=$(df "${line}" | awk '{ s = ""; for (i = 6; i <= NF; i++) s = s $i " "; print s }' | sed '1d' | sed -e 's/[[:space:]]*$//')
		FileSize -d "${MOUNTPOINT}"
		DISPMOUNTPOINT=$(echo "${MOUNTPOINT}" | sed "s/${USER}\///g" | sed "s/\/media\///g" | sed "s/media\///g" | sed "s/\/mnt\///g")
		STRIPPED=$(echo "${MOUNTPOINT}" | sed 's/\/media\///g')
		#if [[ -w "/tmp/mpoint.txt" ]]; then
		#	echo "${MOUNTPOINT}" >> "/tmp/mpoint.txt"
		#fi
		#if [ "${STRIPPED}" = "/" ]; then
		#	STRIPPED="Root"
		#fi

		HDDTMP=$(echo "${line}" | sed 's/[0-9]*//g')
		#Future implementation?
		HDSIZE=$(df -H "${line}" | sed "1d" | awk '{print $2}')

		#See if hddtemp is installed & SUID executable, if not don't do squat
		if [[ "${ISHDDTEMP}" ]]; then

			# TEST 2 conditions:
			# 1. NON-EXISTANT OUTPUT IE USB HDD / Burner
			# 2. Permissions to hddtemp SUID
			# Catch erronious output, eject it to null and skip smart checks.
			TSTVAR=$(hddtemp "${line}" /dev/null 2>&1 |grep 'Permission denied')
			if ! [[ "${TSTVAR}" ]]; then
				TSTVAR=$(hddtemp "${line}" /dev/null 2>&1 | grep -i "t have a temperature sensor.")
				TSTVAR=$(hddtemp "${line}" /dev/null 2>&1 | grep -i "determine")
			fi

			# hddtemp permissions are correct and a sensor exists on current drive.
			if ! [[ "${TSTVAR}" ]]; then
				HDTEMP=$(hddtemp "${line}" --unit=f --numeric)
				SMART=$(echo "${HDTEMP}" | grep -v "S.M.A.R.T. not available")
				SENSOR=$(echo "${HDTEMP}" | grep -v "have a temperature sensor")
			fi
		fi
		#TSPACE=$(expr ${TSPACE} + ${HDSIZE})
		# If Temperature was detected populate Conky as well display info to user.
		if [[ "${NVTEMP}" != "" ]]; then
			Columnize "${line}" "${DISPMOUNTPOINT}" "NVME" "${NVTEMP}°F" "${FORMATTED} bytes (${HDSIZE})"
		else
			Columnize "${line}" "${DISPMOUNTPOINT}" "NVME" "N/A" "${FORMATTED} bytes (${HDSIZE})"
		fi
	done;
}

BenchmarkDisk () {
	DEVICE="${2}"
	if [[ -b "${DEVICE}" ]]; then
		Encapsulate "DEVICE: ${DEVICE}"
	else
		Encapsulate "No device specified or benchmarking boot drive."
	fi
	if [[ -b "${DEVICE}" ]]; then
		LOCATION=$(mount | grep "${DEVICE}" | cut -d " " -f3)
		Center "Benchmarking ${DEVICE} at ${LOCATION}, please wait..."
	else
		Center "Benchmarking current boot drive..."
	fi
	if [[ "${EUID}" == 0 ]]; then
		Encapsulate "Flushing Cache..."
		FLUSH=$(echo 3 | sudo tee /proc/sys/vm/drop_caches 2>/dev/null)
	else
		Encapsulate "Insufficient privilages to flush cache, please run with sudo if you want accurate results, continuing."
	fi
	Encapsulate "Done."
	if [[ "${LOCATION}" ]]; then
		Encapsulate "Benchmarking ${DEVICE} at ${LOCATION}, please wait..."
		Timer "start" "Bench Mark drive..."
		DiskTest "${LOCATION}" & Spinner "Benchmarking ${DEVICE} at ${LOCATION}: "
		Timer "Stop" "Bench Mark drive..."
	else
		Encapsulate "Benchmarking Boot drive, please wait..."
		Timer "start" "Bench Mark boot drive..."
		DiskTest & Spinner "Benchmarking boot drive: "
		Timer "Stop" "Bench Mark boot drive..."
	fi
}

BenchmarkRam () {
	declare -a RAMINFO=();
	declare -a RAMDATA=();
	declare RAMDATA=( "Manufacturer:" "Part Number:" "Speed:" "Type Detail:" "Maximum Capacity:" "Error Correction Type:" "Form Factor:" );
	INDEX=0
	DMIDATA=$(type -p dmidecode)
	if [[ "${DMIDATA}" ]]; then
		for EACH in "${RAMDATA[@]}"
		do
			INDEX=$((INDEX + 1))
			if [[ "${EUID}" == 0 ]]; then
				RAMINFO[${INDEX}]=$(sudo dmidecode --type memory | grep -v "Not Installed" | grep -m 1 --only-matching "${EACH}.*" | sort --unique | grep -v -i "unknown" | grep -v -i "Type: None" )
			else
				if [[ "${RAMDATA}" == 0 ]]; then
					Encapsulate "Advanced Raminfo un-availible without sudo privilages."
				fi
				RAMDATA=1
			fi
			#RAMINFO[${INDEX}]=${OSINFO[${INDEX}]//	/ }
		done
		Center "RAM information:"
		for EACH in "${RAMINFO[@]}"
		do
			Encapsulate "${EACH}"
		done
		declare -i MEMTOTAL
		declare -i SWAPTOTAL
		MEMTOTAL=$(cat /proc/meminfo | grep -i "MemTotal" | cut -d":" -f2 | cut -d "k" -f1)
		GIGS=$(free -m -h | grep -i "mem:" | awk '{print $2}')
		SWAPTOTAL=$(cat /proc/meminfo | grep -i "SwapTotal" | sed "s/ //g" | cut -d ':' -f2 | cut -d "k" -f1)
		SWAPGIG=$(free -m -h | grep -i "swap" | awk '{print $2}')

		#Convert to comma seperated values...Memory
		if [[ "${MEMTOTAL}" && "${GIGS}" ]]; then
			MEMSIZE=$(printf "%'.3f\n" "${MEMTOTAL}")
			MEMORY=$(echo "${MEMSIZE}" | cut -d. -f1)
			Encapsulate "Physical Memory Installed: ${MEMORY} bytes. Gigs: (${GIGS})"
		else
			Error "Cannot retrieve memory information..."
		fi
	else
		Error "RAM INFO not found, not reporting."
	fi
	FullBar
	Center "Benchmarking your RAM (Random Access Memory), please wait..."
	if [[ "${EUID}" == 0 ]]; then
		Encapsulate "Flushing Cache..."
		FLUSH=$(echo 3 | sudo tee /proc/sys/vm/drop_caches 2>/dev/null)
	else
		Encapsulate "Insufficient privilages to flush cache, please run with sudo if you want accurate results, continuing."
	fi
	Encapsulate "Done."
	Timer "start" "Bench Mark RAM"
	RamTest & Spinner "Benchmarking RAM (Random Access Memory): "
	#echo -ne ""
	Timer "Stop" "Bench Mark RAM"
	#IFS=$OIFS
	#RESULTS=$(echo "${RSPEED}" | grep -v "200+")
	#Encapsulate "Ram Speed results: ${RESULTS}"
	#Download "http://os-builder.com/ISOS/ultimate-edition-6.6-x64-lite.iso"
	FullBar
}

RamTest () {
	(LANG=C dd if=/dev/zero of=/dev/null bs=1G count=200 oflag=dsync ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

DiskTest () {
	DEVICE="${1}"
	if [[ -b "${DEVICE}" ]]; then
		(LANG=C dd if=/dev/zero of=/${DEVICE}/benchtest_$$ bs=64k count=200k conv=fdatasync && rm -f benchtest_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
	else
		(LANG=C dd if=/dev/zero of=benchtest_$$ bs=64k count=200k conv=fdatasync && rm -f benchtest_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
	fi
}

BenchmarkDisk () {
	DEVICE="${2}"
	if [[ -b "${DEVICE}" ]]; then
		Encapsulate "DEVICE: ${DEVICE}"
	else
		Encapsulate "No device specified or benchmarking boot drive."
	fi
	if [[ -b "${DEVICE}" ]]; then
		LOCATION=$(mount | grep "${DEVICE}" | cut -d " " -f3)
		Center "Benchmarking ${DEVICE} at ${LOCATION}, please wait..."
	else
		Center "Benchmarking current boot drive..."
	fi
	if [[ "${EUID}" == 0 ]]; then
		Encapsulate "Flushing Cache..."
		FLUSH=$(echo 3 | sudo tee /proc/sys/vm/drop_caches 2>/dev/null)
	else
		Encapsulate "Insufficient privilages to flush cache, please run with sudo if you want accurate results, continuing."
	fi
	Encapsulate "Done."
	if [[ "${LOCATION}" ]]; then
		Encapsulate "Benchmarking ${DEVICE} at ${LOCATION}, please wait..."
		Timer "start" "Bench Mark drive..."
		DiskTest "${LOCATION}" & Spinner "Benchmarking ${DEVICE} at ${LOCATION}: "
		Timer "Stop" "Bench Mark drive..."
	else
		Encapsulate "Benchmarking Boot drive, please wait..."
		Timer "start" "Bench Mark boot drive..."
		DiskTest & Spinner "Benchmarking boot drive: "
		Timer "Stop" "Bench Mark boot drive..."
	fi
}

BenchmarkRam () {
	declare -a RAMINFO=();
	declare -a RAMDATA=();
	declare RAMDATA=( "Manufacturer:" "Part Number:" "Type:" "Speed:" "Type Detail:" "Maximum Capacity:" "Error Correction Type:" );
	INDEX=0
	DMIDATA=$(type -p dmidecode)
	if [[ "${DMIDATA}" ]]; then
		for EACH in "${RAMDATA[@]}"
		do
			INDEX=$((INDEX + 1))
			if [[ "${EUID}" == 0 ]]; then
				RAMINFO[${INDEX}]=$(sudo dmidecode --type memory | grep --only-matching "${EACH}.*" | sort --unique | grep -v -i "unknown" | grep -v -i "Type: None")
			else
				if [[ "${RAMDATA}" == 0 ]]; then
					Encapsulate "Advanced Raminfo un-availible without sudo privilages."
				fi
				RAMDATA=1
			fi
			#RAMINFO[${INDEX}]=${OSINFO[${INDEX}]//	/ }
		done
		Center "RAM information:"
		for EACH in "${RAMINFO[@]}"
		do
			Encapsulate "${EACH}"
		done
		declare -i MEMTOTAL
		declare -i SWAPTOTAL
		MEMTOTAL=$(cat /proc/meminfo | grep -i "MemTotal" | cut -d":" -f2 | cut -d "k" -f1)
		GIGS=$(free -m -h | grep -i "mem:" | awk '{print $2}')
		SWAPTOTAL=$(cat /proc/meminfo | grep -i "SwapTotal" | sed "s/ //g" | cut -d ':' -f2 | cut -d "k" -f1)
		SWAPGIG=$(free -m -h | grep -i "swap" | awk '{print $2}')

		#Convert to comma seperated values...Memory
		if [[ "${MEMTOTAL}" && "${GIGS}" ]]; then
			MEMSIZE=$(printf "%'.3f\n" "${MEMTOTAL}")
			MEMORY=$(echo "${MEMSIZE}" | cut -d. -f1)
			Encapsulate "Physical Memory Installed: ${MEMORY} bytes. Gigs: (${GIGS})"
		else
			Error "Cannot retrieve memory information..."
		fi
	else
		Error "RAM INFO not found, not reporting."
	fi
	FullBar
	Center "Benchmarking your RAM (Random Access Memory), please wait..."
	if [[ "${EUID}" == 0 ]]; then
		Encapsulate "Flushing Cache..."
		FLUSH=$(echo 3 | sudo tee /proc/sys/vm/drop_caches 2>/dev/null)
	else
		Encapsulate "Insufficient privilages to flush cache, please run with sudo if you want accurate results, continuing."
	fi
	Encapsulate "Done."
	Timer "start" "Bench Mark RAM"
	RamTest & Spinner "Benchmarking RAM (Random Access Memory): "
	#echo -ne ""
	Timer "Stop" "Bench Mark RAM"
	#IFS=$OIFS
	#RESULTS=$(echo "${RSPEED}" | grep -v "200+")
	#Encapsulate "Ram Speed results: ${RESULTS}"
	#Download "http://os-builder.com/ISOS/ultimate-edition-6.6-x64-lite.iso"
	FullBar
}

Information () {
	SysInfo
	declare -a OSINFO=();
	declare OSDATA=( "Distributor ID" "Description" "release" "Codename" );
	declare -a SERVICEDATA=();
	INDEX=0
	if [[ -f "/etc/lsb-release" ]]; then
		for EACH in "${OSDATA[@]}"
		do
			INDEX=$((INDEX + 1))
			OSINFO[${INDEX}]=$(lsb_release -ar 2>/dev/null | grep -i "${EACH}")
			OSINFO[${INDEX}]=${OSINFO[${INDEX}]//	/ }
		done
		Center "O/S information:"
		for EACH in "${OSINFO[@]}"
		do
			Encapsulate "${EACH}"
		done
	else
		Error "O/S data not found, not reporting."
	fi
	declare -a CONFIGURATIONINFO=();
	if [[ -f "/var/lib/ram_booter/conf" ]]; then
		OIFS=$IFS
		IFS=$'\n'
		CONFIGURATIONINFO=($(cat "/var/lib/ram_booter/conf" | grep -v "^#" | grep -i "="))
		IFS=$OIFS
		Center "${PROGNAME} Configuration info:"
		for EACH in "${CONFIGURATIONINFO[@]}"
		do
			Encapsulate "${EACH}"
		done
		FullBar
		Center "${PROGNAME} Service data:"
		OIFS=$IFS
		IFS=$'\n'
		SERVICEDATA=$(systemctl status "${APPNAME}")
		IFS=$OIFS
		for EACH in "${SERVICEDATA[@]}"
		do
			Encapsulate "${EACH}"
		done
		FullBar
		if [[ -f "/live/filesystem.squashfs" ]]; then
			Center "${PROGNAME} Size Data:"
			IMAGE_SIZE=$(sudo du -h /live/filesystem.squashfs | awk '{ print $1 }')
			Encapsulate "${PROGNAME} Live file system found at: /live/filesystem.squashfs  Image Size: ${IMAGE_SIZE}"
			OIFS=$IFS
			IFS=$'\n'
			SQFS=($(df "/live/filesystem.squashfs"))
			IFS=$OIFS
			for EACH in "${SQFS[@]}"
			do
				Encapsulate "${EACH}"
			done
		else
			if [[ -f "/ram_session" ]]; then
				Center "Current Session: RAM Session."
			else
				Error "Live file system not found.  Have you ran ${PROGNAME} --setup ?"
			fi
		fi
		if ! [[ -f "/ram_session" ]]; then
			Center "Current Session: Original O/S"
		fi
		BOOTDISK=$(df / | tail -n +2 | cut -d " " -f1)
		Encapsulate "CPU Model:                            $cname"
		Encapsulate "CPU Cores:                            $cores"
		Encapsulate "CPU Frequency:                        $freq MHz ${RESONATION} Mhz /${CPUMAX} (Current / Max / Boost) (BogoMips: ${BOGOMIPS})"
		Encapsulate "CPU Cache:                            $ccache"
		Encapsulate "Total Mem:                            $tram MB ($uram MB Used)"
		Encapsulate "Total Swap:                           $swap MB ($uswap MB Used)"
		Encapsulate "System uptime:                        $up"
		Encapsulate "Kernel:                               $kern"
		Center "Disk Information:"
		Encapsulate "Boot Disk:                          ${BOOTDISK}"
		GREPIT=$(echo "${BOOTDISK}" | grep "nvme")
		if [[ "${GREPIT}" ]]; then
			DRIVETYPE="NVME (Non-Volitile Memory Express)"
			Encapsulate "Drive Type:                         ${DRIVETYPE}"
			SMARTCTL=$(type -p smartctl)
			if [[ "${SMARTCTL}" ]]; then
				NVMEInfo "$@"
				if [[ "${EUID}" == 0 ]]; then
					NVMEMODEL=$(sudo smartctl -a "${BOOTDISK}" | grep "Model Number:")
					NVMECAPACITY=$(sudo smartctl -a "${BOOTDISK}" | grep "Total NVM Capacity:")
					Encapsulate "${NVMEMODEL}"
					Encapsulate "${NVMECAPACITY}"
				else
					Encapsulate "Insufficient privilages to to pull additional data. Please run with sudo if you want accurate results, continuing."
				fi
			fi
			FullBar
		else
			if [[ "${BOOTDISK}" == "overlay" ]]; then
				Encapsulate "Drive Type:                         RAM Drive"
			fi
		fi
	else
		if ! [[ -f "/ram_session" ]]; then
			Center "Current Session: Original O/S"
		fi
		Encapsulate "CPU Model:                            $cname"
		Encapsulate "CPU Cores:                            $cores"
		Encapsulate "CPU Frequency:                        $freq MHz"
		Encapsulate "CPU Cache:                            $ccache"
		Encapsulate "Total Disk:                           $disk_total_size GB ($disk_used_size GB Used)"
		Encapsulate "Total Mem:                            $tram MB ($uram MB Used)"
		Encapsulate "Total Swap:                           $swap MB ($uswap MB Used)"
		Encapsulate "System uptime:                        $up"
		Encapsulate "Kernel:                               $kern"
		#Error "${PROGNAME} has not been setup on this computer, no ${PROGNAME} information availible."
	fi
}

IsInstalled () {
	if ! [[ "${ISARCH}" ]]; then
		INSTALLER=$(type -p dpkg)
		if [[ "${INSTALLER}" ]]; then
			INSTALLED=$(dpkg -l | grep "${2}")
			if [[ "${INSTALLED}" ]]; then
				return 1
			else
				return 0
			fi
		fi
	else
		INSTALLER=$(type -p pacman)
		if [[ "${INSTALLER}" ]]; then
			INSTALLED=$(pacman -S "${2}")
			if [[ "${INSTALLED}" ]]; then
				return 1
			else
				return 0
			fi
		fi
	fi
}

TestBar () {
	Encapsulate "Testing Progress bar"
	i=0
	while [[ $i -ne 100 ]]
	do
        i=$(($i+1))
        ProgressBar "$i" "Testing Progress bar"
		sleep .1
	done
	IsInstalled "ultimate-edition-animated"

	if ! [[ "${INSTALLED}" ]]; then
		Center "Downloading..."
		Download "http://os-builder.com/UETOYS/ultimate-edition-animated-1.0_all.deb"
		if [[ -f "ultimate-edition-animated-1.0_all.deb" ]]; then
			sudo dpkg -i "ultimate-edition-animated-1.0_all.deb"
			rm "ultimate-edition-animated-1.0_all.deb"
		fi
	else
		Encapsulate "ultimate-edition-animated is already installed, skipping."
	fi
	CURRENTBRANCH=$(lsb_release -c | cut -d ":" -f2 | sed "s/ //g" | sed "s/	//g")
	if [[ "${CURRENTBRANCH}" ]]; then
		if [[ "${1}" == "DIST" ]]; then
			Encapsulate "Replacing ${CURRENTBRANCH} with Jammy sources to distribution upgrade."
		else
			Encapsulate "Replacing ${CURRENTBRANCH} with Jammy sources to get the latest kernel."
		fi
		sudo sed -i "s/${CURRENTBRANCH}/jammy/g" "/etc/apt/sources.list"
		Encapsulate "Running apt-get update..."
		sudo apt-get update >/dev/null & Spinner "Running apt-get update..."
		Encapsulate "Installing latest low-latency kernel..."
		if ! [[ "${1}" == "DIST" ]]; then
			sudo DEBIAN_FRONTEND=noninteractive sudo apt-get install -f -y linux-lowlatency linux-headers-lowlatency linux-image-lowlatency & Spinner "Installing latest low-latency kernel..."
		else
			sudo apt-get dist-upgrade -f -y
		fi
		if ! [[ "${1}" == "DIST" ]]; then
			Encapsulate "Replacing jammy sources back to ${CURRENTBRANCH}."
			sudo sed -i "s/jammy/${CURRENTBRANCH}/g" "/etc/apt/sources.list"
			Encapsulate "Running apt-get update..."
			sudo apt-get update >/dev/null & Spinner "Running apt-get update..."
		else
			Encapsulate "Reboot to enjoy your new O/S."
		fi
	else
		Error "Current Branch not detected, exiting."
		exit 1;
	fi
}

