#!/bin/bash
# exhibit - exhibit preparation helper

lib_load 'net/email'
lib_load 'doc/tool/email2pdf'
lib_load 'doc/text'
lib_load 'doc/tool/latex'
lib_load 'sys/tool/git'


######
# Config

doc_legal_exhibit_config_init() {
	lib_setting_vars --null exhibit_case exhibit_timestamp \
		exhibit_offset exhibit_number exhibit_count
	lib_setting_vars --null exhibit_binder_author
	lib_setting_vars --null exhibit_binder_sort

	lib_setting_vars --null exhibitdir
	lib_setting_vars --null exhibit_binderdir
	exhibit_binder_sort=true

	exhibit_case="test"
	exhibit_offset=1
	exhibit_count=1

	lib_setting_vars exhibit_summary_lines
	exhibit_summary_lines=20

	lib_setting_vars --null exhibit_review_state
	lib_setting_vars exhibit_review_type
	exhibit_review_type="${exhibit_review_type:-unknown}"
}

error_if_unset() { declare -p "$1" >/dev/null || error "$1 is not set"; }
run_mkdir_if_set() {
	error_if_unset "$1"
	run_mkdir "$(vecho "$1")"
}

check_exhibitdir() { run_mkdir_if_set "$exhibitdir"; }
check_binderdir() { run_mkdir_if_set "$exhibit_binderdir"; }


######
# Unknown

exhibit_unknown() {
	 warn "$1: unknown file type"
}
exhibit_unknown_view() { exhibit_unknown "$@"; }
exhibit_unknown_view_raw() { exhibit_unknown "$@"; }
exhibit_unknown_view_pdf() { exhibit_unknown "$@"; }
exhibit_unknown_view_summary() { exhibit_unknown "$@"; }


######
# Text Exhibit

exhibit_text_gen() {
	latex_document exhibit_text_gen_head exhibit_text_gen_body "$@"
}
exhibit_text_gen_head() {
	latex_package "geometry" "margin=0.1cm"
}
exhibit_text_gen_body() {
	local file=$1
}

exhibit_text_build() {
	local file=$1
	text_pdf "$file"
	exhibit_text_gen "$file"
}

exhibit_text_view() { run_pager "$1"; }
exhibit_text_view_raw() { run_pager "$1"; }
exhibit_text_view_pdf() { run_text_pdf_viewer "$1"; }
exhibit_text_view_summary() { head -n "$exhibit_summary_lines" "$1"; }


######
# Email Exhibit

exhibit_email_gen() {
	latex_document exhibit_email_gen_head exhibit_emailimg_gen_body "$@"
}
exhibit_email_gen_head() {
	latex_package "geometry" "margin=0.1cm"
}
exhibit_email_gen_body() {
	local file=$1
}

exhibit_email_build() {
	local file=$1
	local subject
	subject=$(email_header "subject")
	exhibit_email_gen "$file"
	email_pdf "$file"
}

exhibit_email_pdf() { email_pdf "$1"; }
exhibit_email_view() { email_view "$1"; }
exhibit_email_view_raw() { run_pager "$1"; }
exhibit_email_view_pdf() { run_email_pdf_viewer "$file"; }
exhibit_email_view_summary() {
	email_headers_simple "$file"
	echo
	email_body "$file" | head -n "$exhibit_summary_lines"
}


######
# Image Exhibit

exhibit_img_gen() {
	latex_document exhibit_img_gen_head exhibit_img_gen_body "$@"
}
exhibit_img_gen_head() {
	latex_package "geometry" "margin=0.1cm"
}
exhibit_img_gen_body() {
	:
}

exhibit_img_build() {
	:
}

exhibit_image_view() { image_view "$1"; }
exhibit_image_view_raw() { run_image_viewer "$1"; }
exhibit_image_view_pdf() { run_image_pdf_viewer "$file"; }
exhibit_image_view_summary() { file "$file"; }


######
# PDF Exhibit

exhibit_pdf_gen() {
	latex_document exhibit_pdf_gen_head exhibit_pdf_gen_body "$@"
}
exhibit_pdf_gen_head() {
	latex_package "geometry" "margin=0.1cm"
}
exhibit_pdf_gen_body() {
	:
}

exhibit_pdf_build() {
	:
}

exhibit_pdf_view() { run_pdf_viewer "$1"; }
exhibit_pdf_view_raw() { run_pdf_viewer "$1"; }
exhibit_pdf_view_pdf() { run_pdf_viewer "$1"; }
exhibit_pdf_view_summary() { file "$1"; }


######
# Generation

exhibit_filename() {
	check_exhibitdir
	echo "$exhibitdir/$exhibit_number.pdf"
}
exhibit_next() { ((exhibit_number++)); }

exhibit_generate() {
	has_args 1 "$@"
	local name=$1
	latex_document exhibit_generate_head exhibit_generate_body "$name"
}

exhibit_generate_head() {
	local name=$1
	latex_package "color"
	latex_tag color "red"

	latex_package "geometry" "margin=0.5in,bottom=0.1in"
#	latex_package "fullpage" "cm"

	latex_page_style "fancyplain"
	latex_tag "lhead" "Exhibit \#$exhibit_number"

	[ -z "$exhibit_case" ] || latex_tag "rhead" "Case \#$exhibit_case"

	local file
	file=$(basename "$name")
	latex_tag "lfoot" "$file"

	latex_package 'lastpage'
	latex_tag "cfoot" '\thepage\ of\ \pageref{LastPage}'

	[ -z "$exhibit_timestamp" ] || latex_tag "rfoot" "$exhibit_timestamp"
}

exhibit_generate_body() {
	local name=$1
	local pages
	pages=$(pdf_page_count "$name")
	for page in $(seq 1 $pages); do
		echo "~\\newpage"
	done
}

exhibit_build() {
	has_args 2 "$@"
	local src=$1
	local dst=$2

	local otmp
	otmp=$(cmd_tempfile)
	pdf_fair_use "$src" "$otmp"

	local etmp
	etmp=$(cmd_tempfile)
	exhibit_generate "$src" >"$etmp"
	latex_pdf "$etmp"

	pdf_overlay "$otmp" "$dst" "$etmp.pdf"
}

######
# Binders

exhibit_binder_list() {
	local cbdir
	cbdir=$(git_repo_dir)
	(
		source "$cbdir/case.conf"
		IFS=$'\n'
		echo "${binders[*]}"
	)
}

exhibit_binderdir() {
	has_args 1 "$@"
	local cbdir=$(exhibit_case_binderdir)
	echo "$cbdir/$1"
}

exhibit_binder_new() {
	local name=$1
	local binderdir
	binderdir=$(exhibit_binderdir "$name")
	[ ! -d "$binderdir" ] || error "$name: binder exists"
	run_mkdir "$binderdir"
}

exhibit_binder_generate() {
	has_args 1 "$@"
	local name=$1
	shift

	local binderdir binderconf
	binderdir=$(exhibit_binderdir "$name")
	binderconf="$binderdir.conf"

	[ -f "$binderconf" ] || error "$name.conf: binder configuration missing"

	local gendir
	gendir=$(exhibit_binderdir "gen/$name")
	run_mkdir "$gendir"

	local -a bfiles
	local file_find_opts=( -type f )
	file_find bfiles "$binderdir"
	! $exhibit_binder_sort || qsort_list bfiles
	local n_files=${#bfiles[@]}

	local exhibit_start=${exhibit_number:-${exhibit_offset:-1}}
	exhibit_number=$exhibit_start
	local -a exhibits
	for file in "${bfiles[@]}"; do
		local -a exhibit
		exhibit=$(printf "$gendir/%04d.pdf" "$exhibit_number")
		exhibits+=( "$exhibit" )
		app_echo "$file: building exhibit $exhibit/$n_files..."
		exhibit_build "$file" "$exhibit"
		exhibit_next
	done
	exhibit_count=$((exhibit_number - exhibit_start))

	local cover
	cover=$(cmd_tempfile)

	local binder_name
	binder_name=$(
		source "$binderconf"
		[ "$name" ] || error "$binderconf: name is not set"
		echo "$name"
	)

	exhibit_number=$exhibit_start
	exhibit_binder_gen_cover "$binder_name" "${bfiles[@]}" >"$cover"
	latex_pdf "$cover"

	# calculate offset
	local cover_page_offset
	cover_page_offset=$(pdf_page_count "$cover.pdf")
	((cover_page_offset++))

	# generate cover again
	exhibit_number=$exhibit_start
	exhibit_binder_gen_cover "$binder_name" "${bfiles[@]}" >"$cover"
	latex_pdf "$cover"

	local pdftk_output="$binderdir.pdf"
	local -a pdftk_inputs=( "$cover.pdf" "${exhibits[@]}" )
	local -a pdftk_op=( cat )
	run_pdftk
}

exhibit_binder_gen_cover() {
	min_args 1 "$@"
	debug "$1: generating ToC"
	latex_document exhibit_binder_gen_head exhibit_binder_gen_body "$@"
}

exhibit_binder_gen_head() {
	local file=$1
	local name
	name=$(basename "$file")
	latex_document_title "$name"
	[ -z "$exhibit_binder_author" ] \
		|| latex_document_author "$exhibit_binder_author"
	latex_document_date_today
}

exhibit_binder_gen_body() {
	local file=$1
	shift

	latex_newpage

	local name
	name=$(basename "$file")
	latex_section "$name Contents"

	local page_number=${cover_page_offset:-1}
	latex_tabular '|r|l|r|' \
		exhibit_binder_toc_header \
		exhibit_binder_toc_entry \
		"$@"
}

exhibit_binder_toc_header() {
	latex_tag hline
	echo 'Number&Name&Page(s)&SHA-1\\'
	latex_tag hline
}

exhibit_binder_toc_entry() {
	local name=$1
	local label
	label=$(basename "$name")

	local sha1sum
	sha1sum=$(sha1sum "$name")

	local pages
	pages=$(pdf_page_count "$name")
	local page_range=$page_number
	if (( pages > 1 )); then
		local last_page=$(($page_number + pages - 1))
		page_range="$page_range--$last_page"
	fi

	echo "$exhibit_number&$label&$page_range&$sha1sum"'\\'

	latex_tag hline
	page_number=$((page_number + pages))
	exhibit_next
}


######
# Case

exhibit_case_binderdir() {
	local casedir
	casedir=$(git_repo_dir)
	echo "$casedir/binders"
}

exhibit_case_list() {
	:
}

exhibit_case_new() {
	local name=$1
	local casedir
	casedir="$(git_repo_dir)/$name"
	[ ! -d "$casedir" ] || error "$name: case exists"
	run_mkdir "$casedir"
}

exhibit_case_update() {
	has_args 1 "$@"
	local file=$1

	local casedir
	casedir=$(git_repo_dir)

	local tmp
	tmp=$(cmd_tempfile)
	sed -e "s, *\t,|,g" "$file" >"$tmp"

	local -a lines
	readarray -t lines <"$tmp"
	for_each exhibit_case_update_one "${lines[@]}"
}

exhibit_case_update_one() {
	has_args 1 "$@"
	local line=$1
	# ensure we found a tab
	if [ "${line/\|/}" = "$line" ]; then
		warn "bad line: $line"
		return 0
	fi

	local exhibit=${line%%|*}
	local -a binders=( ${line#*|} )

	for binder in "${binders[@]}"; do
		local bdir="$casedir/binders/$binder"
		[ -d "$bdir" ] || error "$binder: binder does not exist"

		file_mkdir "$bdir/$exhibit"
		rsync_run --archive "$exhibit" "$bdir/$exhibit"
	done
}

exhibit_case_generate() {
	local tmp
	tmp=$(cmd_tempfile)
	exhibit_binder_list >"$tmp"

	local -a binders
	readarray -t binders <"$tmp"
	for binder in "${binders[@]}"; do
		exhibit_binder_generate "$binder"
	done
}

######
# Review

exhibit_review_type_prompt() {
	has_args 2 "$@"
	local file=$1
	local -n var=$2

	local rtypeglob="text|email|image|pdf"
	while read -p "Select type ($rtypeglob) or 'q' to quit: " -e $2; do
		case "$var" in
		(text|email|image|pdf)
			return 0
			;;
		(q)
			exit 0
			;;
		(*)
			warn "$var: invalid type"
			;;
		esac
	done
}

exhibit_review_type_guess() {
	has_args 1 "$@"
	local file=$1

	info "$file: guessing file type..."
	case "${file##*.}" in
	(txt)
		echo "text"
		;;
	(eml)
		echo "email"
		;;
	(jpg|png)
		echo "image"
		;;
	(pdf)
		echo "pdf"
		;;
	(*)
		echo "unknown"
		;;
	esac
}

exhibit_review_type_probe() {
	has_args 1 "$@"
	local file=$1

	local rtype=$exhibit_review_type
	if [ "$rtype" = "unknown" ]; then
		rtype=$(exhibit_review_type_guess "$file")
	fi

	case "$rtype" in
	(text|email|image|pdf)
		;;
	(*)
		error "$rtype: unknown file type"
		;;
	esac
}

exhibit_review_usage() {
	cat <<USAGE
Exhibit Reviewal Commands:
	view, raw, pdf, summary, skip, pass, add, maybe, remove,
	rescan, type, help, usage, quit
print
USAGE
}

exhibit_review_help() {
	cat <<HELP
View Commands:
	v|view				Views the file
	V|raw				Views the raw file
	p|pdf				Views PDF version of the file
	P|summary			Views a summary of the file

Action Commands:
	t|tag <tag>+			Add tags to the file
	s|skip				Skips the file for good
	S|pass				Skips the file for later
	a|add				Adds the file and marks reviews
	A|maybe				Adds file without marking
	r|remove			Removes a maybe'd file

File Type Commands:
	f|filter <word>+		Filters futher exhibits by word
	R|rescan			Performs a fresh file type scan
	T|type <type>			View as specified file type

General Commands:
	h|?|help			Displays this help
	 |usage				Displays command usage
HELP
}


exhibit_review_file() {
	has_args 1 "$@"
	local file=$1

	_exhibit_review_file "$file"

	local percent=$((100 * exhibit_review_n / exhibit_review_max))
	app_echo "$file: review $percent% done..."
	((exhibit_review_n++))
}

_exhibit_review_file() {
	has_args 1 "$@"
	local file=$1

	for f in "${review_filters[@]}"; do
		if ! grep "$f" "$file" >/dev/null; then
			app_echo "$file: filter '$f' does not match"
			return
		fi
	done

	[ -f "$exhibit_review_state" ] || exhibit_review_reset

	if grep -F "$file" "$exhibit_review_state" >/dev/null 2>&1; then
		app_echo "$file: already reviewed, skipping..."
		return
	fi

	local review_type=$exhibit_review_type
	if ! exhibit_review_type_probe "$file"; then
		exhibit_review_type_prompt "$file" review_type
	fi


	clear
	info "$file: reviewing $review_type file..."
	app_echo "$file:"
	exhibit_${review_type}_view_summary "$file"

	local -a tags
	local default='v'
	local done=false
	local line mark
	local portion="$exhibit_review_n/$exhibit_review_max"
	local prompt="Reviewing $portion [$default]>> "
	while ! $done && read -p "$prompt" -e line; do
		[ "$*" ] || line=$default
		mark=false
		local -a rcmd=( $line )
		case "$rcmd" in
		(q|quit)
			exit
			;;
		(v|view)
			exhibit_${review_type}_view "$file"
			default='a'
			;;
		(V|raw)
			exhibit_${review_type}_view_raw "$file"
			default='a'
			;;
		(p|pdf)
			exhibit_${review_type}_view_pdf "$file"
			default='a'
			;;
		(P|summary)
			exhibit_${review_type}_view_summary "$file"
			;;
		(s|skip|S|pass)
			if [ "${#rcmd[@]}" -eq 0 ]; then
				[ "$line" != 's' -a "$line" != 'skip' ] \
					|| mark=true
				done=true
			else
				warn "$rcmd: too many arguments"
			fi
			;;
		(r|remove)
			run git rm "$file"
			done=true
			;;
		(t|tag)
			tags+=( "${rcmd[@]:1}" )
			mark=true
			done=true
			;;
		(R|rescan)
			exhibit_review_type_probe "$file"
			default='v'
			;;
		(T|type)
			review_type=${rcmd[1]}
			default='v'
			;;
		(f|filter)
			review_filters+=( "${rcmd[@]:1}" )
			;;
		(F|filters)
			echo "active filters: ${review_filters[@]}"
			;;
		(h|help|?)
			exhibit_review_help
			;;
		(usage|'')
			exhibit_review_usage
			;;
		(*)
			warn "$line: unknown command"
			exhibit_review_usage
			;;
		esac

		if $mark; then
			if [ "${tags[*]}" ]; then
				app_echo "$file: marked..."
				echo "$file\t${tags[*]}" >> "$exhibit_review_state"
				run git add "$file"
			else
				warn "$file: no tags specified"
				done=false
			fi
		fi
	done
}

exhibit_review() {
	min_args 1 "$@"
	for_each exhibit_review_top "$@"
}

exhibit_review_top() {
	local top=$1
	local exhibit_review_state="$top.tags"

	local extmp
	extmp=$(cmd_tempfile)

	local -a file_find_opts=( -type f )
	run find "$top" -type f | sort >"$extmp"

	local -a exlist
	readarray -t exlist <"$extmp"
	[ "${exlist[*]}" ] || error "no $exhibit_review_type files found"

	local -a review_filters

	local exhibit_review_n=1
	local exhibit_review_max=${#exlist[@]}
	app_echo "Reviewing $exhibit_review_max $exhibit_review_type files..."
	for_each exhibit_review_file "${exlist[@]}"
}


exhibit_review_reset() {
	[ "$exhibit_review_state" ] || debug=true error
	file_mkdir "$exhibit_review_state"
	: > "$exhibit_review_state"
}

View the Developer Guide Index

View the Reference Manual Index


Generated on Fri Jul 28 14:35:44 PDT 2017 by mcsh d14 v0.23.0.