#!/bin/sh


## Sync with:
# coercion

## Synced paths:
# firefox: ~/.mozilla
# opera: ~/.opera
# claws-mail: ~/.clawz ~/.claws-mail
# skype: ~/.Skype
# misc: ~/media/secure ~/.signature


check=
extra_optz=
dry_run=true

while [[ $# -gt 0 ]]; do
	case "${1}" in
		-h|--help)
			echo >&2 "Usage: ${0} [ -h/--help (this info) | -x (execute) ]"
			echo >&2 "            [ -c (\"complete sync\", adds --delete to rsync) ]"
			exit 0 ;;
		-c) extra_optz="$extra_optz --delete" ;;
		-x) dry_run= ;;
		-*)
			echo >&2 "${0}: unknown option '${1%%=*}'"
			exit 1 ;;
		*)
			if [[ -z "$check" ]]
			then check="$1"
			else
				echo >&2 "${0}: extra argument '${1}'"
				exit 1
			fi ;;
	esac
	shift
done


recursive_mtime() {
	paths=
	for path in $@; do paths="${path/\~/$HOME} $paths"; done
	( find $paths -printf '%T@\n' || echo 0 ) | sort -n | tail -1 | cut -d. -f1
}

run() {
	echo "$@"
	[[ ! $dry_run ]] && "$@"
}


peers="$( gawk '/^## Sync with:$/ {parse=1}
	parse && /^# / {print $2; next}
	parse && !/^#/ {exit}' $0 )"

gawk '/^## Synced paths:$/ {parse=1}
	parse && /^# / {if (match($0, /^# (.*): (.*)$/, dta)) print dta[1], dta[2]; next}
	parse && !/^#/ {exit}' $0 |
while read line; do
	ERR=
	proc=${line%% *}

	## Special-case loop: remote request for specific service mtime
	if [[ -n "$check" ]]; then
		[[ $proc != "$check" ]] && continue
		echo $(recursive_mtime ${line#* }) $(pgrep $proc)
		exit 0
	fi

	pgrep $proc >/dev/null && ERR="$proc is still running"

	# List of max mtimes for every remote
	remote_mtimes=( )
	for peer in $peers; do
		remote_mtime=( "$(ssh -nT $peer "$0 $proc")" )
		[[ -z "$remote_mtime" || $? -ne 0 ]] &&\
			ERR="unable to contact peer $peer"
		[[ ${#remote_mtime[*]} -gt 1 ]] &&\
			ERR="$proc is running on remote ($peer)"
		remote_mtimes=( $peer:${remote_mtime[0]} $remote_mtimes )
	done

	# Get max remote_mtime and peer name
	remote_mtime=$( for remote_mtime in $remote_mtimes
		do echo ${remote_mtime}; done | sort -t: -k2 | tail -1 )
	peer=${remote_mtime%:*}
	remote_mtime=${remote_mtime#*:}

	local_mtime=$(recursive_mtime ${line#* })

	# Sync
	if [[ $remote_mtime -gt $local_mtime ]]; then
		if [[ "$ERR" ]]; then
			echo >&2 "Error: $ERR"
			echo >&2 "\"$proc\" sync skipped"
			continue
		fi
		for path in ${line#* }; do
			rpath="${path/\~/$HOME}"
			if [[ ! -e "$rpath" ]]
			then rpath=$(dirname "$rpath")
			else [[ -d "$rpath" ]] && path="$path/."
			fi
			run rsync -HaAxXzF ${extra_optz} "$peer:$path" "$rpath"
		done
	fi
done
