#!/usr/bin/env bash
# Install and generate motd
# Bryan C. Roessler

main() {
	if [[ " $1 " == " --motd " ]]; then
		print_motd
	else
		parent="${BASH_SOURCE[0]}"
		parent=${parent%/*}

		[[ -f "$parent"/script-functions ]] && . "$parent"/script-functions || exit 1

		is_root

		script="/usr/local/bin/${0##*/}"
		service="/usr/lib/systemd/system/motd.service"
		timer="/usr/lib/systemd/system/motd.timer"

		[[ -f $script ]] || cp "$0" /usr/local/bin/

		install_services
	fi
}

print_motd() {
	# colors
	default='\e[0m'
	green='\e[32m'
	red='\e[31m'
	dim='\e[2m'
	undim='\e[0m'

# shellcheck disable=SC2016
	echo -e \
' _    _            _                           _           _     
| |  | |          | |                         | |         | |    
| |__| | __ _ _ __| |_ _ __ ___   __ _ _ __   | |     __ _| |__  
|  __  |/ _` | `__| __| `_ ` _ \ / _` | `_ \  | |    / _` | `_ \ 
| |  | | (_| | |  | |_| | | | | | (_| | | | | | |___| (_| | |_) |
|_|  |_|\__,_|_|   \__|_| |_| |_|\__,_|_| |_| |______\__,_|_.__/ '

	# System info
	# get load averages
	IFS=" " read -r LOAD1 LOAD5 LOAD15 <<<"$(awk '{ print $1,$2,$3 }' /proc/loadavg)"
	# get free memory
	IFS=" " read -r USED AVAIL TOTAL <<<"$(free -htm | grep "Mem" | awk '{print $3,$7,$2}')"
	# get processes
	PROCESS=$(ps -eo user=|sort|uniq -c | awk '{ print $2 " " $1 }')
	PROCESS_ALL=$(echo "$PROCESS"| awk '{print $2}' | awk '{ SUM += $1} END { print SUM }')
	PROCESS_ROOT=$(echo "$PROCESS"| grep root | awk '{print $2}')
	PROCESS_USER=$(echo "$PROCESS"| grep -v root | awk '{print $2}' | awk '{ SUM += $1} END { print SUM }')
	# get processors
	PROCESSOR_NAME=$(grep "model name" /proc/cpuinfo | cut -d ' ' -f3- | awk '{print $0}' | head -1)
	PROCESSOR_COUNT=$(grep -ioP 'processor\t:' /proc/cpuinfo | wc -l)

	echo -e "
  ${default}Distro......: $default$(cat /etc/*release | grep "PRETTY_NAME" | cut -d "=" -f 2- | sed 's/"//g')
  ${default}Kernel......: $default$(uname -sr)
  ${default}Uptime......: $default$(uptime -p)
  ${default}Load........: $green$LOAD1$default (1m), $green$LOAD5$default (5m), $green$LOAD15$default (15m)
  ${default}Processes...: $default$green$PROCESS_ROOT$default (root), $green$PROCESS_USER$default (user), $green$PROCESS_ALL$default (total)
  ${default}CPU.........: $default$PROCESSOR_NAME ($green$PROCESSOR_COUNT$default vCPU)
  ${default}Memory......: $green$USED$default used, $green$AVAIL$default avail, $green$TOTAL$default total$default"

	# Disk usage
	# config
	max_usage=90
	bar_width=50

	# disk usage: ignore zfs, squashfs & tmpfs
	while IFS= read -r line; do dfs+=("$line"); done < <(df -H -x zfs -x squashfs -x tmpfs -x devtmpfs -x overlay --output=target,pcent,size | tail -n+2)
	printf "\nDisk usage\n"

	for line in "${dfs[@]}"; do
		# get disk usage
		usage=$(echo "$line" | awk '{print $2}' | sed 's/%//')
		used_width=$(((usage*bar_width)/100))
		# color is green if usage < max_usage, else red
		if [ "${usage}" -ge "${max_usage}" ]; then
			color=$red
		else
			color=$green
		fi
		# print green/red bar until used_width
		bar="[${color}"
		for ((i=0; i<used_width; i++)); do
			bar+="="
		done
		# print dimmmed bar until end
		bar+="${default}${dim}"
		for ((i=used_width; i<bar_width; i++)); do
			bar+="="
		done
		bar+="${undim}]"
		# print usage line & bar
		echo "${line}" | awk '{ printf("%-31s%+3s used out of %+4s\n", $1, $2, $3); }' | sed -e 's/^/  /'
		echo -e "${bar}" | sed -e 's/^/  /'
	done

	# # Disk health
	# cat <<- 'EOF' >> "$script"
	# # config
	# MAX_TEMP=40
	# # set column width
	# COLUMNS=2
	# # colors

	# # disks to check
	# disks=(sda sdb sdc sdd sde sdf sdg sdi)
	# disknames=(sda sdb sdc sdd sde sdf sdg sdi)

	# # hddtemp
	# hddtemp_host=localhost
	# hddtemp_port=7634

	# # logfiles to check
	# logfiles='/var/log/syslog /var/log/syslog.1'

	# # get all lines with smartd entries from syslog
	# lines=$(tac $logfiles | grep -hiP 'smartd\[[[:digit:]]+\]:' | grep -iP "previous self-test")
	# # use nc to query temps from hddtemp daemon
	# hddtemp=$(timeout 0.01 nc $hddtemp_host $hddtemp_port | sed 's/|//m' | sed 's/||/ \n/g')

	# out=""
	# for i in "${!disks[@]}"; do
	#     disk=${disks[$i]}
	#     # use disknames if given
	#     diskname=${disknames[$i]}
	#     if [ -z "${diskname}" ]; then
	#         diskname=$disk
	#     fi
	#     uuid=$(blkid -s UUID -o value "/dev/${disk}")
	#     status=$( (grep "${uuid}" <<< "${lines}") | grep -m 1 -oP "previous self-test.*" | awk '{ print $4 " " $5 }')
	#     temp=$( (grep "${disk}" <<< "${hddtemp}") | awk -F'|' '{ print $3 }')

	#     # color green if temp <= MAX_TEMP, else red
	#     if [[ "${temp}" -gt "${MAX_TEMP}" ]]; then
	#         color=$red
	#     else
	#         color=$green
	#     fi
	#     # add "C" if temp is numeric
	#     if [[ "$temp" =~ ^[0-9]+$ ]]; then
	#         temp="${temp}C"
	#     fi
	#     # color green if status is "without error", else red
	#     if [[ "${status}" == "without error" ]]; then
	#         status_color=$green
	#     else
	#         status_color=$red
	#     fi

	#     # print temp & smartd error
	#     out+="${diskname}:,${color}${temp}${undim} | ${status_color}${status}${undim},"
	#     # insert \n every $COLUMNS column
	#     if [ $((($i+1) % $COLUMNS)) -eq 0 ]; then
	#         out+="\n"
	#     fi
	# done
	# out+="\n"

	# printf "\ndisk status:\n"
	# printf "$out" | column -ts $',' | sed -e 's/^/  /'
	# EOF


	# Services
	COLUMNS=2

	services=(
		btrfs-balance.timer btrfs-scrub.timer backup.timer btrbk.timer fstrim.timer
		fail2ban firewalld smb nmb motion smartd cockpit.socket
		dnf-automatic.timer motd.timer
	)

	service_status=()
	# get status of all services
	for service in "${services[@]}"; do
		service_status+=("$(systemctl is-active "$service")")
	done

	out=""
	for i in "${!services[@]}"; do
		# color green if service is active, else red
		if [[ "${service_status[$i]}" == "active" ]]; then
			out+="${services[$i]%.*}:,${green}${service_status[$i]}${undim},"
		else
			out+="${services[$i]%.*}:,${red}${service_status[$i]}${undim},"
		fi
		# insert \n every $COLUMNS column
		if [[ $(((i+1) % COLUMNS)) -eq 0 ]]; then
			out+="\n"
		fi
	done

	printf "\nServices\n"
	printf "%b\n" "$out" | column -ts $',' | sed -e 's/^/  /'


	# Fail2Ban
	# fail2ban-client status to get all jails, takes about ~70ms
	read -r -a jails <<< "$(fail2ban-client status | grep "Jail list:" | sed "s/ //g" | awk '{split($2,a,",");for(i in a) print a[i]}')"

	out="jail,failed,total,banned,total\n"

	for jail in "${jails[@]}"; do
		# slow because fail2ban-client has to be called for every jail (~70ms per jail)
		status=$(fail2ban-client status "$jail")
		failed=$(echo "$status" | grep -ioP '(?<=Currently failed:\t)[[:digit:]]+')
		totalfailed=$(echo "$status" | grep -ioP '(?<=Total failed:\t)[[:digit:]]+')
		banned=$(echo "$status" | grep -ioP '(?<=Currently banned:\t)[[:digit:]]+')
		totalbanned=$(echo "$status" | grep -ioP '(?<=Total banned:\t)[[:digit:]]+')
		out+="$jail,$failed,$totalfailed,$banned,$totalbanned\n"
	done

	printf "\nFail2ban\n"
	printf "%b\n" "$out" | column -ts $',' | sed -e 's/^/  /'

	# Help links
	echo -e '
Links (ctrl+click to follow)
  Server Manual.........: https://tinyurl.com/jjz9h6fr
  Cockpit (for admins)..: http://localhost:9090
  Robot Camera..........: http://localhost:9999
  JupyterLab............: http://localhost:8888
  RStudio Server........: http://localhost:8787
  Robot Computer........: vnc://192.168.16.101:5900
  Windows 10 VM.........: vnc://localhost:5900 (pw: hartman)
	'

	# Scheduled reboot
	if systemctl is-active scheduled-reboot.timer &>/dev/null; then
		echo -n "Next scheduled reboot: "
		time=$(systemctl cat scheduled-reboot.timer | grep OnCalendar=)
		time=${time#*=}
		echo "$time"
	fi
}

install_services() {
	cat <<-EOF > "$service"
		[Unit]
		Description=Generate MoTD

		[Service]
		Type=simple
		ExecStart=/usr/bin/bash -c '$script --motd > /etc/motd'

		[Install]
		WantedBy=default.target
	EOF
	cat <<-'EOF' > "$timer"
		[Unit]
		Description=Generate MoTD every minute on a timer

		[Timer]
		OnCalendar=*:0/1
		OnBootSec=10s

		[Install]
		WantedBy=timers.target
	EOF

	chmod +x "$script" &&
	systemctl daemon-reload &&
	systemctl enable --now "${timer##*/}"
}

main "$@"

exit $?