#!/bin/sh
#
# Processes main.cpp with regexes to find out commands and sub-commands.
# This is not as evil as it looks because upstream is doing the same thing in
# gen_help_txt.sh which runs as part of check_help_text github CIrworkflow.

set -eu
set -o pipefail

COMMANDS=$(sed -n '/^vector<std::shared_ptr<cmd>> commands {$/,/^};$/p' main.cpp | sed -ne 's/        std::shared_ptr<cmd>(new \([a-z0-9_]\+\)_command()),/\1/p' | xargs)

if [ "$COMMANDS" != "info config load encrypt seal link save erase verify otp partition uf2 version coprodis" ]; then
	echo "E: unexpected commands: $COMMANDS" >&2
	exit 1
fi
# there is no mbedtls (FIXME?) so remove encrypt and seal subcommands
# special-case reboot and help
COMMANDS="info config load link save erase verify reboot otp partition uf2 version coprodis help"

SUB_COMMANDS=$(sed -ne 's/^vector<std::shared_ptr<cmd>> \([a-z0-9_]*\)_sub_commands {$/\1/p' main.cpp | xargs)
if [ "$SUB_COMMANDS" != "partition otp uf2" ]; then
	echo "E: unexpected sub_commands: $SUB_COMMANDS" >&2
	exit 1
fi

PARTITION_SUB_COMMANDS=$(sed -n '/^vector<std::shared_ptr<cmd>> partition_sub_commands {$/,/^};$/p' main.cpp | sed -ne 's/        std::shared_ptr<cmd>(new partition_\([a-z0-9_]\+\)_command()),/\1/p' | xargs)
if [ "$PARTITION_SUB_COMMANDS" != "info create" ]; then
	echo "E: unexpected partition sub_commands: $PARTITION_SUB_COMMANDS" >&2
	exit 1
fi

OTP_SUB_COMMANDS=$(sed -n '/^vector<std::shared_ptr<cmd>> otp_sub_commands {$/,/^};$/p' main.cpp | sed -ne 's/        std::shared_ptr<cmd>(new otp_\([a-z0-9_]\+\)_command()),/\1/p' | xargs)
if [ "$OTP_SUB_COMMANDS" != "list get set load dump permissions white_label" ]; then
	echo "E: unexpected otp sub_commands: $OTP_SUB_COMMANDS" >&2
	exit 1
fi
# replace white_label by white-label
OTP_SUB_COMMANDS="list get set load dump permissions white-label"

UF2_SUB_COMMANDS=$(sed -n '/^vector<std::shared_ptr<cmd>> uf2_sub_commands {$/,/^};$/p' main.cpp | sed -ne 's/        std::shared_ptr<cmd>(new uf2_\([a-z0-9_]\+\)_command()),/\1/p' | xargs)
if [ "$UF2_SUB_COMMANDS" != "info convert" ]; then
	echo "E: unexpected uf2 sub_commands: $UF2_SUB_COMMANDS" >&2
	exit 1
fi

if [ "$#" -ne 4 ]; then
	echo "E: missing arguments" >&2
	exit 1
fi

generate_man() {
	"./obj-$DEB_HOST_GNU_TYPE/picotool" help | ./debian/help2md.pl "picotool" >./debian/man/picotool.md
	pandoc ./debian/man/picotool.md -s -t man -o ./debian/man/picotool.1 --metadata="footer:picotool ${VERSION_UPSTREAM}" --metadata="date: ${DATE_MONTH_YEAR}"
	# toplevel commands
	for cmd in $COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help "$cmd" | ./debian/help2md.pl "$cmd" >"./debian/man/picotool-$cmd.md"
		pandoc "./debian/man/picotool-$cmd.md" -s -t man -o "./debian/man/picotool-${cmd}.1" --metadata="footer:picotool ${VERSION_UPSTREAM}" --metadata="date: ${DATE_MONTH_YEAR}"
	done
	# partition subcommands
	for cmd in $PARTITION_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help partition "$cmd" | ./debian/help2md.pl "partition $cmd" >"./debian/man/picotool-partition-$cmd.md"
		pandoc "./debian/man/picotool-partition-$cmd.md" -s -t man -o "./debian/man/picotool-partition-${cmd}.1" --metadata="footer:picotool ${VERSION_UPSTREAM}" --metadata="date: ${DATE_MONTH_YEAR}"
	done
	# otp subcommands
	for cmd in $OTP_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help otp "$cmd" | ./debian/help2md.pl "otp $cmd" >"./debian/man/picotool-otp-$cmd.md"
		pandoc "./debian/man/picotool-otp-$cmd.md" -s -t man -o "./debian/man/picotool-otp-${cmd}.1" --metadata="footer:picotool ${VERSION_UPSTREAM}" --metadata="date: ${DATE_MONTH_YEAR}"
	done
	# uf2 subcommands
	for cmd in $UF2_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help uf2 "$cmd" | ./debian/help2md.pl "uf2 $cmd" >"./debian/man/picotool-uf2-$cmd.md"
		pandoc "./debian/man/picotool-uf2-$cmd.md" -s -t man -o "./debian/man/picotool-uf2-${cmd}.1" --metadata="footer:picotool ${VERSION_UPSTREAM}" --metadata="date: ${DATE_MONTH_YEAR}"
	done
}

verify_man() {
	diff=$(mktemp)
	trap 'rm -f -- "$diff"' EXIT
	"./obj-$DEB_HOST_GNU_TYPE/picotool" help | ./debian/help2md.pl "picotool" | diff -u ./debian/man/picotool.md - >>"$diff" && echo "./debian/man/picotool.md: OK" || echo "./debian/man/picotool.md: FAIL"
	# toplevel commands
	for cmd in $COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help "$cmd" | ./debian/help2md.pl "$cmd" | diff -u "./debian/man/picotool-$cmd.md" - >>"$diff" && echo "./debian/man/picotool-$cmd.md: OK" || echo "./debian/man/picotool-$cmd.md: FAIL"
	done
	# partition subcommands
	for cmd in $PARTITION_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help partition "$cmd" | ./debian/help2md.pl "partition $cmd" | diff -u "./debian/man/picotool-partition-$cmd.md" - >>"$diff" && echo "./debian/man/picotool-partition-$cmd.md: OK" || echo "./debian/man/picotool-partition-$cmd.md: FAIL"
	done
	# otp subcommands
	for cmd in $OTP_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help otp "$cmd" | ./debian/help2md.pl "otp $cmd" | diff -u "./debian/man/picotool-otp-$cmd.md" - >>"$diff" && echo "./debian/man/picotool-otp-$cmd.md: OK" || echo "./debian/man/picotool-otp-$cmd.md: FAIL"
	done
	# uf2 subcommands
	for cmd in $UF2_SUB_COMMANDS; do
		"./obj-$DEB_HOST_GNU_TYPE/picotool" help uf2 "$cmd" | ./debian/help2md.pl "uf2 $cmd" | diff -u "./debian/man/picotool-uf2-$cmd.md" - >>"$diff" && echo "./debian/man/picotool-uf2-$cmd.md: OK" || echo "./debian/man/picotool-uf2-$cmd.md: FAIL"
	done
	if [ -s "$diff" ]; then
		echo "E: picotool help output differs from cached version:"
		cat "$diff"
		exit 1
	fi
}

DEB_HOST_GNU_TYPE=$2
VERSION_UPSTREAM=$3
DATE_MONTH_YEAR=$4

case "$1" in
generate) generate_man ;;
verify) verify_man ;;
*)
	echo "E: unknown option: $1" >&2
	exit 1
	;;
esac
