#!/bin/sh

# puts tags on their own lines (possibly joining multi-line tags), and
# normalises whitespace
parse_html() {
	sed 's/</\n</g;s/>/>\n/g' | sed ':f;/</!b;/>/b;N;s/\n/ /;b f' | sed 's/^[[:space:]]*//;/^$/d'
}

# only gives forms from HTML, separated by "%- - - -%" lines
get_forms() {
	parse_html | sed '/^<form/,/^<\/form/!d;s#</form.*>#&\n%- - - -%#'
}

# cut lines at least 69 characters long to 65 characters followed by ellipsis
truncate_lines() {
	sed 's#^\(.\{65\}\).....*$#\1...#'
}

# put everything in a "%- - - -%" delimited paragraph on one line
# (newlines are converted into $1)
linify() {
	sed '/^%- - - -%$/{;s/.*//;x;s#\n#'"$1"'#g;b;};H;d'
}

# Turn form fields into RFC822-header reminescent (or RFC2849) notation.
make_form() {
	NAME="\\([^ \"'=<>\`/]\\{1,\\}\\)"
	wg --address | sed 's/^/*base: /'
	sed '/^%- - - -%$/b;/^</! s/^/# /' | \
	sed "s#$NAME *= *'*$NAME'*"'#\1="\2"#g' | \
	sed 's#^<.*action *= *"\([^"]*\).*$#*action: \1#' | \
	sed 's#^<.*name *= *"\([^"]*\).*value *= *"\([^"]*\).*$#\1: \2#' | \
	sed 's#^<.*value *= *"\([^"]*\).*name *= *"\([^"]*\).*$#\2: \1#' | \
	sed 's#^<.*name *= *"\([^"]*\).*$#\1: #;/^</d'
}

# Takes RFC822-header input and throws out all values
only_fields() {
	sed '/^#/d;/^.base:/d;/^.action:/b;s/^\([^:]*\): .*$/\1/'
}

# Format "%- - - -%" delimited RFC822 style form data into concise list
show_formfile_nicely () {
	only_fields | linify '; ' | truncate_lines
}

# Pick $1'th line (if a digit) or first line matching $1 (otherwise)
pick_line_by() {
	case "$1" in
	[1-9]) sed -ne "$1 p" ;;
	*) sed "/$1/!d;q" ;;
	esac
}

# Same as pick_line_by, but works on "%- - - -%" delimited paragraphs
pick_paragraph_by() {
	linify '%-%-%' | pick_line_by "$PATTERN" | sed 's#%-%-%#\n#g;s#^\n##'
}

# append filled form in file $1 to "%- - - -%" delimited form log file $2
save_form() {
	cat "$1" >> "$2"
	echo '%- - - -%' >> "$2"
}

test -z "$WG_DIR" && WG_DIR="$HOME/.wg"
test -z "$FORMFILE" && FORMFILE="$WG_DIR/lastform"
test -z "$FORMHISTORY" && FORMHISTORY="$WG_DIR/formhistory"
test -z "$EDITOR" && EDITOR=sensible-editor

PATTERN=
INPUT="wg -r"
MODE=fill

while test -n "$1"; do
	case "$1" in
	-l|--list) MODE=list ;;
	--list-raw) MODE=listraw ;;
	--list-debug) MODE=listdebug ;;
	-h|--history) MODE=history ;;
	-q|--quick) MODE=quick ;;
	-) INPUT=cat ;;
	-*) echo "formfill: unknown option $1" 1>&2 ;;
	*) PATTERN="$1" ;;
	esac
	shift
done

if test -n "$PATTERN"; then
	# in fill and history modes, get the form denoted by $PATTERN
	# from the current page ($INPUT) or the history, respectively.
	# The form is put into $FORMFILE in RFC822-like syntax.
	case "$MODE" in
	fill) $INPUT | get_forms | make_form | \
		pick_paragraph_by "$PATTERN" > "$FORMFILE" ;;
	history)
		cat "$FORMHISTORY" | pick_paragraph_by "$PATTERN" > "$FORMFILE"
		MODE=fill ;;
	*) echo "Warning: pattern '$PATTERN' overridden by mode" 1>&2 ;;
	esac
fi

case "$MODE" in
	list) $INPUT | get_forms | make_form | show_formfile_nicely | cat -n ;;
	listraw) $INPUT | get_forms ;;
	listdebug) $INPUT | get_forms | make_form ;;
	history) cat "$FORMHISTORY" | show_formfile_nicely | cat -n ;;
	fill)
		"$EDITOR" "$FORMFILE"
		# TODO implement cancelling
		save_form "$FORMFILE" "$FORMHISTORY"
		send_form "$FORMFILE" ;;
esac
