#!/usr/bin/env bash
# upload -- transfer files to my public "upload bin"

. lib.bash || exit
. ~/bin/lib/libks.bash || exit

usage() {
	echo "Usage: $progname [options] <file>…"
	echo ""
	echo_opt "-0"		"do not use yearly subdirectories"
	echo_opt "-1"		"upload to fs1 instead of main site"
	echo_opt "-c"		"continue upload / overwrite file"
	echo_opt "-d path"	"create a subdirectory"
	echo_opt "-i"		"connect interactively (using lftp)"
	echo_opt "-ii"		"connect using gvfs-ftp"
	echo_opt "-iii"		"connect using NFS"
	echo_opt "-q"		"quiet -- no transfer progress, no clipboard"
	echo_opt "-S regex"	"mangle (sed) the destination filename"
	echo_opt "-t"		"add 'Ymd' timestamps to destination filenames"
	echo_opt "-tt"		"add Unix timestamps"
	echo_opt "-ttt"		"add 'Ymd.HMS' timestamps"
	echo_opt "-T"		"use file modification time as timestamp"
	echo_opt "-X"		"delete files instead of uploading"
}

r:test() {
	local test=$1 host=${2%%:*} path=${2#*:}
	ks:sshrun "$host" test $test "$path"
}

r:mkdir() {
	local host=${1%%:*} path=${1#*:}
	ks:sshrun "$host" mkdir -p "$path"
}

r:rm_rvf() {
	local host=${1%%:*} path=${1#*:}
	ks:sshrun "$host" rm -rvf "$path"
}

declare -a rsync
declare -A fsbase urlbase

fsbase="star:pub/symlink/tmp"
urlbase="https://symlink.lt/tmp"

fsbase[fs1]="ember:/srv/http/fs1/tmp"
urlbase[fs1]="https://fs1.symlink.lt/tmp"

rsync=(
	--copy-links
	--chmod="a+r"
)

# parse command line

declare -i arg_clobber=0
declare -i arg_interactive=0
declare -- arg_mangle=
declare -i arg_quiet=0
declare -i arg_remove=0
declare -- arg_server=
declare -- arg_subdir=
declare -i arg_timestamp=0
declare -i arg_mtime=0
declare -i arg_yearly=1

while getopts ":01cd:iqS:tTX" OPT; do
	case $OPT in
	0) arg_yearly=0;;
	1) arg_server=fs1;;
	c) arg_clobber=1;;
	d) arg_subdir=$OPTARG;;
	i) arg_interactive+=1;;
	q) arg_quiet=1;;
	S) arg_mangle=$OPTARG;;
	t) arg_timestamp+=1;;
	T) arg_mtime=1;;
	X) arg_remove=1;;
	*) lib:die_getopts;;
	esac
done; shift $((OPTIND-1))

if [[ $arg_server ]]; then
	fsbase=${fsbase[$arg_server]}
	urlbase=${urlbase[$arg_server]}
	if ! [[ $fsbase && $urlbase ]]; then
		die "unknown server '$arg_server'"
	fi
fi

if [[ $arg_subdir == /* ]]; then
	arg_yearly=0
	arg_subdir="${arg_subdir#/}"
fi

if (( arg_yearly )); then
	year=$(date +%Y)
	fsbase+="/$year"
	urlbase+="/$year"
fi

if [[ $arg_subdir ]]; then
	fsbase+="/$arg_subdir"
	urlbase+="/$arg_subdir"
fi

debug "base dir: '$fsbase'"
debug "base url: '$urlbase'"

if (( arg_mtime && !arg_timestamp )); then
	arg_timestamp=1
fi

if (( arg_timestamp >= 3 )); then
	timefmt='%Y%m%d.%H%M%S.'
elif (( arg_timestamp == 2 )); then
	timefmt='%s.'
elif (( arg_timestamp == 1 )); then
	timefmt='%Y%m%d.'
fi

if (( !$# && !arg_interactive )); then
	die "missing file names"
elif (( $# && arg_interactive )); then
	warn "ignoring file arguments in interactive mode"
fi

# prepare upload target

if [[ $arg_server || $arg_subdir ]]; then
	# $arg_server is a hack, until I copy rotate-up.sh to all other servers
	r:mkdir "$fsbase"
fi

# handle special modes

if (( arg_interactive >= 3 )); then
	rhome=$(ks:sshrun "${fsbase%%:*}" printenv HOME)
	case $fsbase in
		*:/*) url="/net/${fsbase%%:*}${fsbase#*:}";;
		*:*)  url="/net/${fsbase%%:*}${rhome%/}/${fsbase#*:}";;
	esac
	if (( arg_quiet )); then
		echo "$url"
	elif [[ $DISPLAY || $WAYLAND_DISPLAY ]]; then
		gio open "$url"
	else
		vmsg "starting a shell at $url"
		env -C "$url" bash
	fi
	exit
elif (( arg_interactive == 2 )); then
	rhome=$(ks:sshrun "${fsbase%%:*}" printenv HOME)
	case $fsbase in
		*:/*) url="sftp://${fsbase%%:*}${fsbase#*:}";;
		*:*)  url="sftp://${fsbase%%:*}${rhome%/}/${fsbase#*:}";;
	esac
	if (( arg_quiet )); then
		echo "$url"
	elif [[ $DISPLAY || $WAYLAND_DISPLAY ]]; then
		gio info -f "$url" &> /dev/null || gio mount "$url"
		gio open "$url"
	else
		vdie "no X11 or Wayland; can't start Nautilus SFTP"
	fi
	exit
elif (( arg_interactive == 1 )); then
	if have lftp; then
		case $fsbase in
			*:/*) url="sftp://${fsbase%%:*}${fsbase#*:}";;
			*:*)  url="sftp://${fsbase%%:*}/~/${fsbase#*:}";;
		esac
		lftp "$url"
	elif have sftp; then
		addr="$fsbase/"
		sftp "$addr"
	else
		die "couldn't find a known SFTP client"
	fi
	exit
fi

# upload files

clip=()

if (( ! arg_quiet )); then
	rsync+=("-P")
fi

for arg; do
	if (( ! arg_remove )); then
		if [[ ! -f $arg ]]; then
			err "'$arg' is not a file"
			continue
		elif [[ ! -s $arg ]]; then
			warn "'$arg' is empty, skipping"
			continue
		fi
	fi

	name=${arg##*/}
	# yay special case
	if [[ $name == Screencast?from* ]]; then
		name=$(sed -E "s/^Screencast from //; s/ /./g; s/://g" <<< "$name")
	fi
	if [[ $arg_subdir == cap ]]; then
		name=$(sed -E 's/ .*(\.[a-z]+)$/\1/' <<< "$name")
	fi
	if [[ $arg_mangle ]]; then
		name=$(sed -E "$arg_mangle" <<< "$name")
	fi
	if (( arg_timestamp && arg_mtime )); then
		name=$(date +"$timefmt" -r "$arg")$name
	elif (( arg_timestamp )); then
		name=$(date +"$timefmt")$name
	fi
	source=$(realpath -s "$arg")
	target="$fsbase/$name"
	url="$urlbase/$(urlencode -a "$name")"
	debug "* source: '$source'"
	debug "  target: '$target'"
	debug "  url: '$url'"

	if (( arg_remove )); then
		r:rm_rvf "$target"
	else
		if r:test -s "$target" && ! (( arg_clobber )); then
			err "'$name' already exists on server"
			continue
		fi
		if ! rsync -st "${rsync[@]}" "$source" "$target" >&2; then
			err "upload of '$source' to '$target' failed"
			continue
		fi

		if (( arg_quiet )); then
			echo "$url"
		else
			echo "$name => $url"
			clip+=("$url")
		fi
	fi
done

if (( ${#clip[@]} )) && gclip -q &> /dev/null; then
	echo -n "${clip[*]}" | gclip
fi

(( !errors ))
