#!/usr/bin/env bash
# dropbatch -- submit jobs to other PCs via Dropbox/Syncthing
#
# Jobs are processed by 'cron.dropbatch'.

. lib.bash || exit

usage() {
	echo "Usage: $progname [-n] [-w] HOST [FILE]"
	echo "Usage: $progname -l [-n] [-w] [HOST]"
	echo
	echo "Place a script in ~/Dropbox to be run by another host's dropbatch.service"
	echo
	echo_opt "-l"		"list all stored jobs and their output files"
	echo_opt "-n"		"place script directly on remote host via NFS"
	echo_opt "-w"		"wait and show job output when it appears"
	echo
	echo "Jobs submitted with the -w option are stored in a separate location; they"
	echo "are only listed if -w is specified together with -l."
}

dolist=0
usenfs=0
wait=0

while getopts :lnw OPT; do
	case $OPT in
	l) dolist=1;;
	n) usenfs=1;;
	w) wait=1;;
	*) lib:die_getopts;;
	esac
done; shift $((OPTIND-1))

host=${1%%.*}
script=$2

if [[ ! $host ]] && (( !dolist || usenfs )); then
	vdie "missing hostname"
fi

if (( usenfs )); then
	targetdir=/n/${host?}/Dropbox
else
	targetdir=~/Dropbox
fi

if (( wait )); then
	targetdir=$targetdir/.System/Batch
fi

if (( dolist )); then
	for path in "$targetdir"/[a-z]*-[0-9]*.sh*; do
		file=${path##*/}
		if [[ $host && $file != "$host"-* ]]; then
			continue
		fi
		if ! [[ $file =~ ^([a-z]+)-([0-9]+)\.sh(\.done|\.log)?$ ]]; then
			continue
		fi
		jhost=${BASH_REMATCH[1]}
		jtime=${BASH_REMATCH[2]}
		jstatus=${BASH_REMATCH[3]}
		jdate=$(date -d "@$jtime" +"%b %-d, %H:%M")
		printf '%s\t%s\t%s\t%s\n' \
			"$jtime" "$jdate" "$jhost" "$path"
	done \
	| sort -t $'\t' -k 1 -n \
	| column -t -s $'\t' -N TIME,DATE,HOST,FILE -H TIME -O DATE,HOST,FILE
	exit
fi

if [[ ! $script || $script == "-" ]]; then
	tmp=$(mktemp /tmp/job.XXXXXXXX.sh)
	echo '#!/bin/bash' > "$tmp"
	if [[ ! $script && -t 0 ]]; then
		${EDITOR:-vi} "$tmp"
	else
		cat > "$tmp"
	fi
	if ! grep -vqs "^#!" "$tmp"; then
		vmsg "script is empty"
		rm -f "$tmp"
		exit
	fi
	script=$tmp
elif [[ ! -f $script ]]; then
	vdie "script file '$script' not found"
elif [[ ! -s $script ]]; then
	vmsg "script file is empty"
	exit
fi

dest=$targetdir/$host-$(date +%s).sh

cp "$script" "$dest.tmp" &&
chmod u+x "$dest.tmp" &&
mv "$dest.tmp" "$dest" &&
rm "$script" || exit

vmsg "job $dest submitted"

if (( wait )); then
	vmsg "waiting for job to be processed..."
	time=0
	if (( usenfs )); then
		# For submissions over NFS, wait for the job to complete before
		# checking -- doing it too quickly will populate negative stat
		# cache which takes 30 seconds to expire.
		time=3; sleep $time
	fi
	until [[ -e $dest.done ]]; do
		printf '\rWaiting (%ds)...' $[time++]
		sleep 1
	done
	printf '\n'
	if [[ -e $dest.log ]]; then
		vmsg "job finished"
	else
		vmsg "job finished, waiting for result..."
		time=0
		until [[ -e $dest.log ]]; do
			printf '\rWaiting (%ds)...' $[time++]
			sleep 1
		done
		printf '\n'
	fi
	${PAGER:-cat} "$dest.log"
fi
