# Tiny Cloud - common script functions
# vim:set filetype=sh:
# shellcheck shell=sh

# set defaults
: "${ETC:=$ROOT/etc}"
: "${PROC:=$ROOT/proc}"
: "${SYS:=$ROOT/sys}"
[ -f "$ETC/tiny-cloud.conf" ] && . "$ETC/tiny-cloud.conf"
: "${CLOUD:=auto}"
: "${CLOUD_USER:=alpine}"
mkdir -p "${TINY_CLOUD_LOGS:=$ROOT/var/log}"
mkdir -p "${TINY_CLOUD_VAR:=$ROOT/var/lib/cloud}"

log() {
	local facility="local7"
	local stderr init
	local tag=$(basename "$0")
	while [ "${1#-}" != "$1" ]; do
		case "$1" in
			-i) init=1 ;;
			-f) facility="$2"; shift ;;
			-s) stderr=-s ;;
			-t) tag="$tag/$2"; shift ;;
		esac
		shift
	done
	local level="$1"
	[ -z "$DEBUG" ] && [ "$level" = debug ] && return
	shift

	[ -n "$init" ] && echo "$@" >&2
	logger $stderr -p "$facility.$level" -t "${tag}[$$]" -- "$@"
	case "$level" in
		crit|alert|emerg) exit 1 ;;
	esac
}

lower() { tr 'A-Z' 'a-z'; }
line_has_k() {
	# <key> [<file>] - line(s) in stdin/<file> have <key> defined?
	cat "${2:--}" 2>/dev/null | xargs -n1 | cut -d= -f1 | grep -q "^$1$"
}
line_kval() {
	# <key> [<file>] [<chars>] - <key> value(s) from stdin/<file> line(s)
	#	replace output <chars> with spaces (suitable for "sub-kv" situations)
	cat "${2:--}" 2>/dev/null | xargs -n1 | grep "^$1=" | cut -d= -f2- | paste -sd' ' | tr "$3" ' '
}

if [ "$CLOUD" = "auto" ]; then
	# previously detected?
	CLOUD=$(cat "$TINY_CLOUD_VAR"/.autodetect 2>/dev/null) || {
		# try kernel cmdline & DMI product serial
		for F in "$PROC/cmdline" "$SYS/class/dmi/id/product_serial"; do
			CLOUD=$(line_kval tinycloud "$F" : | line_kval cloud)
			[ -z "$CLOUD" ] && CLOUD=$(line_kval ds "$F" ';' | cut -d' ' -f1 | lower)
			[ -n "$CLOUD" ] && break
		done
		if [ -n "$CLOUD" ]; then
			# convert cloud-init cloud names
			case "$CLOUD" in
				ec2) CLOUD=aws;;
				gce) CLOUD=gcp;;
				nocloud-net) CLOUD=nocloud;;
				oracle) CLOUD=oci;;
			esac
		else
			# try all the autodetects, sorted by confidence...
			CLOUD=$(
				for i in "$LIBDIR"/tiny-cloud/cloud/*/autodetect; do
					[ -x "$i" ] && "$i"
				done | sort -n | cut -d' ' -f2 | head -n 1
			)
		fi
		if [ -z "$CLOUD" ] || [ ! -d "$LIBDIR/tiny-cloud/cloud/$CLOUD" ]; then
			log -t autodetect err "unable to determine cloud"
			CLOUD=unknown
		else
			log -t autodetect notice "choosing '$CLOUD' cloud"
			printf "%s\n" "$CLOUD" > "$TINY_CLOUD_VAR"/.autodetect
		fi
	}
fi

# usage: replace_word <search> <replace> <list>...
replace_word() {
	local search="$1" replace="$2"
	shift 2
	for word in "$@"; do
		if [ "$word" = "$search" ]; then
			echo "$replace"
		else
			echo "$word"
		fi
	done
}

# usage: insert_after <where> <what> <list>...
insert_before() {
	local search="$1" addition="$2"
	shift 2
	for i in "$@"; do
		if [ "$i" = "$search" ]; then
			echo "$addition"
		fi
		echo "$i"
	done
}

# usage: insert_after <where> <what> <list>...
insert_after() {
	local search="$1" addition="$2"
	shift 2
	for i in "$@"; do
		echo "$i"
		if [ "$i" = "$search" ]; then
			echo "$addition"
		fi
	done
}

# usage: add_once <file> <line-to-add>...
add_once() {
	local file="$1"
	shift
	for line; do
		if ! grep -x -F "$line" "$file" 2>/dev/null; then
			mkdir -p "${file%/*}"
			printf "%s\n" "$line" >> "$file"
		fi
	done
}
