#!/usr/bin/env bash

# multilockscreen
# i3lock wrapper with multi-monitor support
# https://github.com/jeffmhubbard/multilockscreen

init_config () {

	# default options
	display_on=0
	span_image=false
	lock_timeout=300
	fx_list=(dim blur dimblur pixel dimpixel color)
	dim_level=40
	blur_level=1
	pixel_scale=10,1000
	solid_color=333333
	description=""

	# default theme
	loginbox=00000066
	loginshadow=00000000
	locktext="Type password to unlock..."
	font="sans-serif"
	ringcolor=ffffffff
	insidecolor=00000000
	separatorcolor=00000000
	ringvercolor=ffffffff
	insidevercolor=00000000
	ringwrongcolor=ffffffff
	insidewrongcolor=d23c3dff
	keyhlcolor=d23c3dff
	bshlcolor=d23c3dff
	verifcolor=ffffffff
	timecolor=ffffffff
	datecolor=ffffffff
	layoutcolor=ffffffff
	nocolor=00000000
	bgcolor=000000ff

	# read user config
	USER_CONF="$HOME/.config/multilock/config"
	if [ -e "$USER_CONF" ]; then
		# shellcheck source=/dev/null
		source "$USER_CONF"
	fi

	# paths
	CACHE_DIR="$HOME/.cache/multilock"
	CUR_DIR="$CACHE_DIR/current"

	# wallpaper
	CUR_W_RESIZE="$CUR_DIR/wall_resize.png"
	CUR_W_DIM="$CUR_DIR/wall_dim.png"
	CUR_W_BLUR="$CUR_DIR/wall_blur.png"
	CUR_W_DIMBLUR="$CUR_DIR/wall_dimblur.png"
	CUR_W_PIXEL="$CUR_DIR/wall_pixel.png"
	CUR_W_DIMPIXEL="$CUR_DIR/wall_dimpixel.png"
	CUR_W_COLOR="$CUR_DIR/wall_color.png"

	# lockscreen
	CUR_L_RESIZE="$CUR_DIR/lock_resize.png"
	CUR_L_DIM="$CUR_DIR/lock_dim.png"
	CUR_L_BLUR="$CUR_DIR/lock_blur.png"
	CUR_L_DIMBLUR="$CUR_DIR/lock_dimblur.png"
	CUR_L_PIXEL="$CUR_DIR/lock_pixel.png"
	CUR_L_DIMPIXEL="$CUR_DIR/lock_dimpixel.png"
	CUR_L_COLOR="$CUR_DIR/lock_color.png"

	# Original DPMS timeout
	DEFAULT_TIMEOUT=$(cut -d ' ' -f4 <<< "$(xset q | sed -n '25p')")
	# Original DPMS status
	DEFAULT_DPMS=$(xset q | awk '/^[[:blank:]]*DPMS is/ {print $(NF)}')
}

# called before screen is locked
prelock() {

	# set dpms timeout
	if [ "$DEFAULT_DPMS" == "Enabled" ]; then
		xset dpms "$lock_timeout"
	fi
	# pause dunst
	if command -v dunstctl &>/dev/null
	then
		dunstctl set-paused true
	fi
}

# lock screen with specified image
lock() {

	echof act "Locking screen..."

	local image="$1"

	i3lock \
		-i "$image" \
		-c "$bgcolor" \
		--screen "$display_on" \
		--time-pos='ix-170:iy-0' \
		--date-pos='ix-240:iy+25' \
		--layout-pos='ix-90:iy-0' --layout-align 1 --layout-color=$layoutcolor $keylayout \
		--clock --date-align 1 --date-str "$locktext" \
		--inside-color=$insidecolor --ring-color=$ringcolor --line-uses-inside \
		--keyhl-color=$keyhlcolor --bshl-color=$bshlcolor --separator-color=$separatorcolor \
		--insidever-color=$insidevercolor --insidewrong-color=$insidewrongcolor \
		--ringver-color=$ringvercolor --ringwrong-color=$ringwrongcolor --ind-pos='x+280:y+h-70' \
		--radius=20 --ring-width=4 --verif-text='' --wrong-text='' --wrong-color="$nocolor" \
		--verif-color="$verifcolor" --time-color="$timecolor" --date-color="$datecolor" \
		--time-font="$font" --date-font="$font" --layout-font="$font" --verif-font="$font" --wrong-font="$font" \
		--noinput-text='' --force-clock --pass-media-keys --pass-screen-keys --pass-power-keys \
		"${lockargs[@]}"
}

# in case image isn't found
failsafe() {

	echof act "Locking screen... (FAILSAFE MODE)"

	local bgcolor="000000"
	local text="ffffffff"
	local error="ff0000"

	i3lock \
		-c "$bgcolor" \
		--screen "$display_on" \
		--time-pos='ix-170:iy-0' \
		--date-pos='ix-240:iy+25' \
		--clock --date-align 1 --date-str "$locktext" \
		--ind-pos='x+280:y+h-70' \
		--radius=20 --ring-width=4 --verif-text='' --wrong-text='' --wrong-color="$error" \
		--verif-color="$text" --time-color="$text" --date-color="$text" \
		--time-font="$font" --date-font="$font" --layout-font="$font" --verif-font="$font" --wrong-font="$font" \
		--noinput-text='' --force-clock
}


# called after screen is unlocked
postlock() {

	# restore default dpms timeout
	if [ "$DEFAULT_DPMS" == "Enabled" ]; then
		xset dpms "$DEFAULT_TIMEOUT"
	fi

	# unpause dunst
	if command -v dunstctl &>/dev/null
	then
		dunstctl set-paused false
	fi
}


# select effect and lock screen
lockselect() {

	echof act "Running prelock..."
	prelock &

	case "$1" in
		dim) if [ -f "$CUR_L_DIM" ]; then lock "$CUR_L_DIM"; else failsafe; fi ;;
		blur) if [ -f "$CUR_L_BLUR" ]; then lock "$CUR_L_BLUR"; else failsafe; fi ;;
		dimblur) if [ -f "$CUR_L_DIMBLUR" ]; then lock "$CUR_L_DIMBLUR"; else failsafe; fi ;;
		pixel) if [ -f "$CUR_L_PIXEL" ]; then lock "$CUR_L_PIXEL"; else failsafe; fi ;;
		dimpixel) if [ -f "$CUR_L_DIMPIXEL" ]; then lock "$CUR_L_DIMPIXEL"; else failsafe; fi ;;
		color) if [ -f "$CUR_L_COLOR" ]; then lock "$CUR_L_COLOR"; else failsafe; fi ;;
		*) if [ -f "$CUR_L_RESIZE" ]; then lock "$CUR_L_RESIZE"; else failsafe; fi ;;
	esac

	echof act "Running postlock..."
	postlock &
}

# calculate adjustments for hidpi displays
logical_px() {

	# $1: number of pixels to convert
	# $2: 1 for width. 2 for height
	local pixels="$1"
	local direction="$2"

	# get dpi value from xdpyinfo
	local DPI
	DPI=$(xdpyinfo | sed -En "s/\s*resolution:\s*([0-9]*)x([0-9]*)\s.*/\\$direction/p" | head -n1)

	# return the default value if no DPI is set
	if [ -z "$DPI" ]; then
		echo "$pixels"
	else
		local SCALE
		SCALE=$(echo "scale=2; $DPI / 96.0" | bc)

		# check if scaling the value is worthy
		if [ "$(echo "$SCALE > 1.25" | bc -l)" -eq 0 ]; then
			echo "$pixels"
		else
			echo "$SCALE * $pixels / 1" | bc
		fi
	fi
}

# get total resolution, sets $TOTAL_SIZE
get_total_size () {
	TOTAL_SIZE=$(xdpyinfo | grep -w "dimensions" | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/')
}

# get list of displays, sets $DISPLAY_LIST
get_display_list () {
	local count=0
	mapfile -t displays < <(xrandr --listactivemonitors)
	for display in "${displays[@]:1}"; do
		((count++))
		display="$(echo "$display" | sed -r 's/\/[0-9]*//g')"
		IFS=' ' read -r -a info  <<< "$display"
		DISPLAY_LIST+=("$count ${info[3]} ${info[2]}")
	done
}

# populate $WALL_LIST depending on number of displays and images passed
get_wall_list() {

	local paths=("$@")
	declare -ga WALL_LIST

	# multiple images and spanning conflict, bail out
	if [ "${#paths[@]}" -gt 1 ] && [ "$span_image" = true ]; then
		echof err "Can't use --span with multiple images!"
		exit 1
	fi

	# if spanning return 1 image
	if [ "$span_image" = true ]; then
		get_image "${paths[0]}"

	# if # paths is 1
	elif [ "${#paths[@]}" -eq 1 ]; then
		for ((i=0; i<${#DISPLAY_LIST[@]}; i++)); do
			# add same image to $WALL_LIST for each display
			get_image "${paths[0]}"
		done

	# if # of paths equals # of displays
	elif [ ${#paths[@]} -eq "${#DISPLAY_LIST[@]}" ]; then
		for ((i=0; i<${#DISPLAY_LIST[@]}; i++)); do
			# add each image to $WALL_LIST
			get_image "${paths[$i]}"
		done

	# if # of paths differ from # of display, bail out
	else
		echof err "${#paths[@]} images provided for ${#DISPLAY_LIST[@]} displays!"
		exit 1
	fi
}

# get image path, append to $WALL_LIST
get_image() {

	local path="$1"

	# we have a file
	if [ -f "$path" ]; then
		WALL_LIST+=("$path")
		return
	# we have a directory
	elif [ -d "$path" ]; then
		dir=("$path"/*)
		rdir="${dir[RANDOM % ${#dir[@]}]}"
		get_image "$rdir" # <-- calls itself
	# not file or directory, bail out
	else
		echof err "invalid path: $path"
		exit 1
	fi

}

# scale base image and generate effects
resize_and_render () {

	local base="$1"
	local path="$2"
	local resolution="$3"

	# resource paths
	RES_RESIZE="$path/resize.png"
	RES_DIM="$path/dim.png"
	RES_BLUR="$path/blur.png"
	RES_DIMBLUR="$path/dimblur.png"
	RES_PIXEL="$path/pixel.png"
	RES_DIMPIXEL="$path/dimpixel.png"
	RES_COLOR="$path/color.png"

	# resize
	base_resize "$base" "$RES_RESIZE" "$resolution"

	# effects
	for effect in "${fx_list[@]}"; do
		case $effect in
			dim) fx_dim "$RES_RESIZE" "$RES_DIM";;
			blur) fx_blur "$RES_RESIZE" "$RES_BLUR" "$resolution";;
			dimblur) fx_dimblur "$RES_RESIZE" "$RES_DIMBLUR" "$resolution";;
			pixel) fx_pixel "$RES_RESIZE" "$RES_PIXEL";;
			dimpixel) fx_dimpixel "$RES_RESIZE" "$RES_DIMPIXEL";;
			color) fx_color "$RES_COLOR" "$resolution";;
		esac
	done

}

# apply resize
base_resize() {

	local input="$1"
	local output="$2"
	local size="$3"

	echof act "Resizing base image..."
	eval convert "$input" \
		-resize "$size""^" \
		-gravity center \
		-extent "$size" \
		"$output"
}

# apply dim
fx_dim() {
	local input="$1"
	local output="$2"

	echof act "Rendering 'dim' effect..."
	eval convert "$input" \
		-fill black -colorize "$dim_level"% \
		"$output"
}

# apply blur
fx_blur() {
	local input="$1"
	local output="$2"
	local size="$3"

	echof act "Rendering 'blur' effect..."
	blur_shrink=$(echo "scale=2; 20 / $blur_level" | bc)
	blur_sigma=$(echo "scale=2; 0.6 * $blur_level" | bc)
	eval convert "$input" \
		-filter Gaussian \
		-resize "$blur_shrink%" \
		-define "filter:sigma=$blur_sigma" \
		-resize "$size^" -gravity center -extent "$size" \
		"$output"
}

# apply dimblur
fx_dimblur() {
	local input="$1"
	local output="$2"
	local size="$3"

	echof act "Rendering 'dimblur' effect..."
	blur_shrink=$(echo "scale=2; 20 / $blur_level" | bc)
	blur_sigma=$(echo "scale=2; 0.6 * $blur_level" | bc)
	eval convert "$input" \
		-fill black -colorize "$dim_level"% \
		-filter Gaussian \
		-resize "$blur_shrink%" \
		-define "filter:sigma=$blur_sigma" \
		-resize "$size^" -gravity center -extent "$size" \
		"$output"
}

# pixelate
fx_pixel() {
	local input="$1"
	local output="$2"

	echof act "Rendering 'pixel' effect..."
	IFS=',' read -ra range <<< "$pixel_scale"
	eval convert "$input" \
		-scale "${range[0]}"% -scale "${range[1]}"% \
		"$output"
}

# apply dimpixel
fx_dimpixel() {
	local input="$1"
	local output="$2"

	echof act "Rendering 'dimpixel' effect..."
	IFS=',' read -ra range <<< "$pixel_scale"
	eval convert "$input" \
		-fill black -colorize "$dim_level"% \
		-scale "${range[0]}"% -scale "${range[1]}"% \
		"$output"
}

# create solid color
fx_color() {
	local output="$1"
	local size="$2"

	echof act "Rendering 'color' effect..."
	eval convert -size "$size" canvas:\#"$solid_color" "$RES_COLOR"
}

# create loginbox rectangle, set $RECTANGLE
create_loginbox () {
	RECTANGLE="$CUR_DIR/rectangle.png"
	local shadow="$CUR_DIR/shadow.png"
	local width height
	width=$(logical_px 300 1)
	height=$(logical_px 80 2)
	convert -size "$width"x"$height" xc:\#"$loginbox" -fill none $RECTANGLE
	convert $RECTANGLE \
		\( -clone 0 -background \#"$loginshadow" -shadow 100x5+0+0 \) +swap \
		-background none -layers merge +repage $shadow
	composite -compose Dst_Out -gravity center \
		$RECTANGLE $shadow -alpha Set $shadow
	convert $shadow $RECTANGLE -geometry +10+10 -composite $RECTANGLE
	[[ $shadow ]] && rm $shadow
}

# create rectangle with description, set $DESCRECT
create_description () {
	DESCRECT="$CUR_DIR/description.png"
	local shadow="$CUR_DIR/shadow.png"
	convert -background none -family "$(fc-match "$font" family)" -style Normal -pointsize 14 -fill \#"$datecolor" label:"\ $description\ " -bordercolor \#"$loginbox" -border 10 $DESCRECT
	convert $DESCRECT \
		\( -clone 0 -background \#"$loginshadow" -shadow 100x5+0+0 \) +swap \
		-background none -layers merge +repage $shadow
	composite -compose Dst_Out -gravity center \
		$DESCRECT $shadow -alpha Set $shadow
	convert $shadow $DESCRECT -geometry +10+10 -composite $DESCRECT
	[[ $shadow ]] && rm $shadow
}

# delete and recreate directory
purge_cache () {
	if [[ -d "$1" ]]; then
		rm -r "$1"
	fi
	mkdir -p "$1"
}

# update lockscreen and wallpaper images
update () {

	local images=("$@")

	echof act "Updating image cache..."
	mkdir -p "$CACHE_DIR" &>/dev/null

	get_display_list # DISPLAY_LIST
	get_total_size # TOTAL_SIZE
	echof info "Detected ${#DISPLAY_LIST[@]} display(s) @ $TOTAL_SIZE total resolution"

	get_wall_list "${images[@]}" # WALL_LIST
	echof info "Original image(s): ${WALL_LIST[*]##*/}"

	# Prepare description box to obtain width for positioning
	if [ -z "$description" ]; then
		local descwidth=0
		local descheight=0
	else
		create_description
		local descwidth=$(identify -format "%[fx:w]" "$DESCRECT")
		local descheight=$(identify -format "%[fx:h]" "$DESCRECT")
	fi

	for ((i=0; i<${#DISPLAY_LIST[@]}; i++)); do
		display="${DISPLAY_LIST[$i]}"
		USER_WALL="${WALL_LIST[$i]}"

		# escape spaces for IM
		if echo "$USER_WALL" | grep -E -q "[[:space:]]"; then
			USER_WALL="${USER_WALL// /\\ }"
		fi

		IFS=' ' read -r -a dinfo  <<< "$display"
		local id="${dinfo[0]}"
		local device="${dinfo[1]}"
		local geometry="${dinfo[2]}"

		read -r -a cols <<< "${geometry//[x+-]/ }"
		local position="${geometry#*${cols[1]}}"
		local resolution="${geometry%${position}*}"

		if [[ $id -eq "$display_on" ]] || [[ "$display_on" -eq 0 ]]; then

			IFS='x' read -r -a dimension <<< "$resolution"
			res_x="${dimension[0]}"
			res_y="${dimension[1]}"
			read -r -a val <<< "${position//[+-]/ }"
			read -r -a sym <<< "${position//[0-9]/ }"
			pos_x="${sym[0]}${val[0]}"
			pos_y="${sym[1]}${val[1]}"

			rect_x=$((pos_x + $(logical_px 15 1)))
			rect_y=$((pos_y + res_y - $(logical_px 120 2)))
			positions+=("+$((rect_x))+$((rect_y))")

			descrect_x=$((pos_x + res_x - descwidth - $(logical_px 15 1)))
			descrect_y=$((pos_y + res_y - descheight - $(logical_px 20 2)))
			positions_desc+=("+$((descrect_x))+$((descrect_y))")
		fi

		local path="$CACHE_DIR/$id-$device"
		purge_cache "$path"

		if [ "$span_image" = true ]; then
			if [ "$id" -gt 1 ]; then
				continue
			else
				device="[span]"
				id="*"
				resolution="$TOTAL_SIZE"
			fi
		fi

		echof info "Processing display: $device ($id)"
		echof info "Resolution: $resolution"

		if [ "$span_image" = true ]; then
			resize_and_render "$USER_WALL" "$path" "$resolution"
		else
			resize_and_render "$USER_WALL" "$path" "$resolution"

			PARAM_RESIZE="$PARAM_RESIZE $RES_RESIZE -geometry $position -composite "
			PARAM_DIM="$PARAM_DIM $RES_DIM -geometry $position -composite "
			PARAM_BLUR="$PARAM_BLUR $RES_BLUR -geometry $position -composite "
			PARAM_DIMBLUR="$PARAM_DIMBLUR $RES_DIMBLUR -geometry $position -composite "
			PARAM_PIXEL="$PARAM_PIXEL $RES_PIXEL -geometry $position -composite "
			PARAM_DIMPIXEL="$PARAM_DIMPIXEL $RES_DIMPIXEL -geometry $position -composite "
			PARAM_COLOR="$PARAM_COLOR $RES_COLOR -geometry $position -composite "
		fi

	done

	purge_cache "$CUR_DIR"

	if [ "$span_image" = true ] || [ ${#DISPLAY_LIST[@]} -lt 2 ]; then
		echof act "Rendering final wallpaper images..."
		[[ -f "$RES_RESIZE" ]] && cp $RES_RESIZE $CUR_W_RESIZE
		[[ -f "$RES_DIM" ]] && cp $RES_DIM $CUR_W_DIM
		[[ -f "$RES_BLUR" ]] && cp $RES_BLUR $CUR_W_BLUR
		[[ -f "$RES_DIMBLUR" ]] && cp $RES_DIMBLUR $CUR_W_DIMBLUR
		[[ -f "$RES_PIXEL" ]] && cp $RES_PIXEL $CUR_W_PIXEL
		[[ -f "$RES_DIMPIXEL" ]] && cp $RES_DIMPIXEL $CUR_W_DIMPIXEL
		[[ -f "$RES_COLOR" ]] && cp $RES_COLOR $CUR_W_COLOR
	else
		echof act "Creating canvas: $TOTAL_SIZE"
		[[ -f "$RES_RESIZE" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_RESIZE
		[[ -f "$RES_DIM" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_DIM
		[[ -f "$RES_BLUR" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_BLUR
		[[ -f "$RES_DIMBLUR" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_DIMBLUR
		[[ -f "$RES_PIXEL" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_PIXEL
		[[ -f "$RES_DIMPIXEL" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_DIMPIXEL
		[[ -f "$RES_COLOR" ]] && convert -size $TOTAL_SIZE 'xc:blue' $CUR_W_COLOR

		echof act "Rendering final wallpaper images..."
		[[ -f "$CUR_W_RESIZE" ]] && convert $CUR_W_RESIZE $PARAM_RESIZE $CUR_W_RESIZE
		[[ -f "$CUR_W_DIM" ]] && convert $CUR_W_DIM $PARAM_DIM $CUR_W_DIM
		[[ -f "$CUR_W_BLUR" ]] && convert $CUR_W_BLUR $PARAM_BLUR $CUR_W_BLUR
		[[ -f "$CUR_W_DIMBLUR" ]] && convert $CUR_W_DIMBLUR $PARAM_DIMBLUR $CUR_W_DIMBLUR
		[[ -f "$CUR_W_PIXEL" ]] && convert $CUR_W_PIXEL $PARAM_PIXEL $CUR_W_PIXEL
		[[ -f "$CUR_W_DIMPIXEL" ]] && convert $CUR_W_DIMPIXEL $PARAM_DIMPIXEL $CUR_W_DIMPIXEL
		[[ -f "$CUR_W_COLOR" ]] && convert $CUR_W_COLOR $PARAM_COLOR $CUR_W_COLOR
	fi

	echof act "Rendering final lockscreen images..."

	create_loginbox
	for pos in "${positions[@]}"; do
		PARAM_RECT="$PARAM_RECT $RECTANGLE -geometry $pos -composite "
	done

	if [ ! -z "$description" ]; then
		create_description
		for descpos in "${positions_desc[@]}"; do
			PARAM_RECT="$PARAM_RECT $DESCRECT -geometry $descpos -composite "
		done
	fi

	[[ -f "$CUR_W_RESIZE" ]] && convert $CUR_W_RESIZE $PARAM_RECT $CUR_L_RESIZE
	[[ -f "$CUR_W_DIM" ]] && convert $CUR_W_DIM $PARAM_RECT $CUR_L_DIM
	[[ -f "$CUR_W_BLUR" ]] && convert $CUR_W_BLUR $PARAM_RECT $CUR_L_BLUR
	[[ -f "$CUR_W_DIMBLUR" ]] && convert $CUR_W_DIMBLUR $PARAM_RECT $CUR_L_DIMBLUR
	[[ -f "$CUR_W_PIXEL" ]] && convert $CUR_W_PIXEL $PARAM_RECT $CUR_L_PIXEL
	[[ -f "$CUR_W_DIMPIXEL" ]] && convert $CUR_W_DIMPIXEL $PARAM_RECT $CUR_L_DIMPIXEL
	[[ -f "$CUR_W_COLOR" ]] && convert $CUR_W_COLOR $PARAM_RECT $CUR_L_COLOR

	[[ $RECTANGLE ]] && rm "$RECTANGLE"
	[[ $DESCRECT ]] && rm "$DESCRECT"

	echof ok "Done"

}

# set wallpaper with effect
wallpaper() {

	local effect="$1"
	local span

	# make wallpaper span displays
	get_display_list
	if [ "$span_image" = true ] || [[ "${#DISPLAY_LIST[@]}" -gt 1 ]]; then
		span="--no-xinerama"
	fi

	# set wallpaper
	case "$effect" in
		dim) feh --bg-fill "$span" "$CUR_W_DIM";;
		blur) feh --bg-fill "$span" "$CUR_W_BLUR";;
		dimblur) feh --bg-fill "$span" "$CUR_W_DIMBLUR";;
		pixel) feh --bg-fill "$span" "$CUR_W_PIXEL";;
		dimpixel) feh --bg-fill "$span" "$CUR_W_DIMPIXEL";;
		color) feh --bg-fill "$span" "$CUR_W_COLOR";;
		*) feh --bg-fill "$span" "$CUR_W_RESIZE";;
	esac
}

# wrap echo with fancy prefix
echof() {

	local prefix="$1"
	local message="$2"

	case "$prefix" in
		header) msgpfx="[\e[1;95mm\e[m]";;
		info) msgpfx="[\e[1;97m=\e[m]";;
		act) msgpfx="[\e[1;92m*\e[m]";;
		ok) msgpfx="[\e[1;93m+\e[m]";;
		error) msgpfx="[\e[1;91m!\e[m]";;
		*) msgpfx="";;
	esac
	echo -e "$msgpfx $message"
}

# help message
usage() {
	echo
	echo "Usage: multilockscreen [-u <PATH>] [-l <EFFECT>] [-w <EFFECT>]"
	echo
	echo "  -u --update <PATH>"
	echo "      Update lock screen image"
	echo
	echo "  -l --lock <EFFECT>"
	echo "      Lock screen with cached image"
	echo
	echo "  -w --wall <EFFECT>"
	echo "      Set wallpaper with cached image"
	echo
	echo "Additional arguments:"
	echo
	echo "  --display <N>"
	echo "      Set display to draw loginbox"
	echo
	echo "  --span"
	echo "      Scale image to span multiple displays"
	echo
	echo "  --off <N>"
	echo "      Turn display off after N minutes"
	echo
	echo "  --fx <EFFECT,EFFECT,EFFECT>"
	echo "      List of effects to generate"
	echo
	echo "  --desc <DESCRIPTION>"
	echo "      Set a description for the new lock screen image"
	echo "      (Only has an effect in combination with --update)"
	echo
	echo "  --show-layout"
	echo "      Show current keyboard layout"
	echo
	echo "  -- <ARGS>"
	echo "      Pass additional arguments to i3lock"
	echo
	echo "Effects arguments:"
	echo
	echo "  --dim <N>"
	echo "      Dim image N percent (0-100)"
	echo
	echo "  --blur <N>"
	echo "      Blur image N amount (0.0-1.0)"
	echo
	echo "  --pixel <N,N>"
	echo "      Pixelate image with N shrink and N grow (unsupported)"
	echo
	echo "  --color <HEX>"
	echo "      Solid color background with HEX"
	echo
	exit 1
}

echof header "multilockscreen"

init_config

# show usage when no arguments passed
[[ "$1" = "" ]] && usage

# process arguments
lockargs=()
for arg in "$@"; do
	[[ "${arg:0:1}" = '-' ]] || continue

	case "$1" in
		-u | --update)
			runupdate=true
			imagepaths+=("$2")
			shift 2
			;;

		-s | --suspend)
			runsuspend=true
			;&

		-l | --lock)
			runlock=true
			if [[ ${2:0:1} = '-' ]]; then
				shift 1
			else
				lockstyle="$2"; shift 2
			fi
			;;

		-w | --wall)
			wallpaper "$2"
			shift 2
			;;

		--display)
			display_on="$2"
			shift 2
			;;

		--span)
			span_image=true
			shift 1
			;;

		--off)
			lock_timeout="$2"
			shift 2
			;;

		--text)
			locktext="$2"
			shift 2
			;;

		--show-layout)
			keylayout="--keylayout 2";
			shift 1
			;;

		--fx)
			IFS=',' read -ra fx_list <<< "$2"
			shift 2
			;;

		--dim)
			dim_level="$2"
			shift 2
			;;

		--blur)
			blur_level="$2"
			shift 2
			;;

		--pixel)
			pixel_scale="$2"
			shift 2
			;;

		--color)
			solid_color="${2//\#/}"
			shift 2
			;;

		--desc)
			description="$2"
			shift 2
			;;

		--)
			lockargs+=("${@:2}")
			break
			;;

		-h | --help | *)
			usage
			break
			;;
	esac
done

# Run image generation
[[ $runupdate ]] && update "${imagepaths[@]}"

# Activate lockscreen
[[ $runsuspend ]] || lockargs+=(-n)
[[ $runlock ]] && lockselect "$lockstyle" && \
	{ [[ $runsuspend ]] && systemctl suspend; }

exit 0
