#!/usr/bin/env bash

. lib.bash || exit

hdd_spindown() {
	if have sg_start; then
		sudo sg_start --stop --readonly --immed "$1"
	elif have scsi_stop; then
		sudo scsi_stop "$1"
	elif have hdparm; then
		sudo hdparm -y "$1"
	else
		err "missing SCSI & SATA userspace tools"
	fi
}

hdd_poweroff() {
	if have hdparm; then
		sudo hdparm -Y "$1"
	else
		err "missing SCSI & SATA userspace tools"
	fi
}

# load configuration

declare -i mount
declare -A alias outer_uuid

config_file=${XDG_CONFIG_HOME}/nullroute.lt/gmount.conf.sh

if [[ -e $config_file ]]; then
	. "$config_file" || die "could not load configuration"
fi

# parse command line

mount=1
standby=0
poweroff=0
media="/run/media/$USER"

if [[ ${0##*/} == gumount ]]; then
	mount=0
fi

while getopts ":duyY" OPT; do
	case $OPT in
	d) mount=0;;
	u) mount=0;;
	y) mount=0; standby=1;;
	Y) mount=0; poweroff=1;;
	*) lib:die_getopts;;
	esac
done; shift $((OPTIND-1))

if (( ! $# )); then
	die "volume not given"
fi

if [[ $SSH_CONNECTION ]]; then
	b=$'\e[1m' r=$'\e[m'
	h=$HOSTNAME i=${SSH_CONNECTION%% *}
	warn "Running over SSH on $b$h$r (you are connecting from $b$i$r)"
fi

# mount volumes

shopt -s nullglob

for dir in /run/media/$USER/*/; do
	if ! mountpoint -q "$dir"; then
		info "found stale mountpoint '$dir'"
		sudo: rmdir "$dir"
		sudo: systemctl reset-failed
	fi
done

for arg; do
	arg=${alias[$arg]:-$arg}

	if (( mount || standby || poweroff )); then
		if [[ $arg == /* ]]; then
			dev=$arg
			if [[ ! -e $dev ]]; then
				err "nonexistent device '$dev'"
				continue
			elif [[ ! -b $dev || $dev != /dev/sd* ]]; then
				err "bad device path '$dev'"
				continue
			else
				debug "accepting device path '$arg'"
			fi
		elif [[ $arg == sd* ]]; then
			dev=/dev/$arg
			if [[ ! -e $dev ]]; then
				err "nonexistent device '$dev'"
				continue
			else
				debug "accepting device name '$arg'"
			fi
		elif [[ ${outer_uuid[$arg]} ]]; then
			uuid=${outer_uuid[$arg]}
			debug "searching for outer ID/UUID '$uuid'"
			if [[ -e "/dev/disk/by-id/$uuid" ]]; then
				dev=$(readlink -f "/dev/disk/by-id/$uuid")
			elif [[ -e "/dev/disk/by-partuuid/$uuid" ]]; then
				dev=$(readlink -f "/dev/disk/by-partuuid/$uuid")
			elif [[ -e "/dev/disk/by-uuid/$uuid" ]]; then
				dev=$(readlink -f "/dev/disk/by-uuid/$uuid")
			else
				info "waiting for device '$uuid' to appear"
				while [[ ! $dev ]] && read -r ipath ievent iname; do
					debug "got event: <$ipath> <$ievent> <$iname>"
					if [[ $iname == "$uuid" ]]; then
						dev=$(readlink -f "$ipath$iname")
						debug "matched event for device '$dev'"
						sleep 0.5
					fi
				done < <(timeout 30 inotifywait -rmqe create /dev/disk)
				if [[ ! $dev ]]; then
					die "disk with UUID '$uuid' not found"
				fi
			fi
		else
			debug "searching for outer device '$arg'"
			if [[ -e "/dev/disk/by-id/$arg" ]]; then
				dev=$(readlink -f "/dev/disk/by-id/$arg")
			elif [[ -e "/dev/disk/by-partlabel/$arg" ]]; then
				dev=$(readlink -f "/dev/disk/by-partlabel/$arg")
			elif [[ -e "/dev/disk/by-label/$arg" ]]; then
				dev=$(readlink -f "/dev/disk/by-label/$arg")
			elif [[ -e "/dev/disk/by-partuuid/$arg" ]]; then
				dev=$(readlink -f "/dev/disk/by-partuuid/$arg")
			elif [[ -e "/dev/disk/by-uuid/$arg" ]]; then
				dev=$(readlink -f "/dev/disk/by-uuid/$arg")
			else
				die "disk with label '$arg' not found"
			fi
		fi
	fi

	if (( mount )); then
		info "mounting $dev"
		gio mount -d "$dev"
	else
		if [[ $arg == /dev/* ]]; then
			mtpt=$(findmnt -n -o TARGET -S "$arg")
		else
			debug "searching for inner label/uuid '$arg'"
			outer_id=${outer_uuid["$arg"]:-"$arg"}
			mtpt=$(findmnt -n -o TARGET -S "/dev/disk/by-id/$outer_id" \
				|| findmnt -n -o TARGET -S "PARTLABEL=$arg" \
				|| findmnt -n -o TARGET -S "LABEL=$arg" \
				|| findmnt -n -o TARGET -S "PARTUUID=$arg" \
				|| findmnt -n -o TARGET -S "UUID=$arg")
		fi
		if [[ $mtpt ]]; then
			info "unmounting $mtpt"
			gio mount -u "$mtpt" || err "unmount failed"
		elif ! (( standby || poweroff )); then
			err "mountpoint not found"
		fi &&

		if (( standby )); then
			dev=${dev%[0-9]}
			info "putting $dev to standby"
			hdd_spindown "$dev"
		elif (( poweroff )); then
			dev=${dev%[0-9]}
			info "powering off $dev"
			hdd_poweroff "$dev"
		fi
	fi
done
((!errors))
