#!/usr/bin/env bash

set -o errexit -o nounset -o pipefail

myshuf() {
	if type shuf > /dev/null 2>&1; then
		command shuf $*
	else
		awk 'BEGIN { srand() } { printf "%s\t%s\n", rand(), $0 }' |
			sort -k1,1n |
			cut -f2- |
			head -n1
	fi
}

find_random_manpage() {
	OLDIFS=$IFS
	IFS=:
 	for dir in $(manpath -q); do
 		[[ -n $dir ]] && printf "%s\n" $dir/man{1,2}/* 2>/dev/null | grep -v perl
 	done | myshuf -n 1
	IFS=$OLDIFS
}

get_description_of_manpage() {
	# source: https://stackoverflow.com/a/3352015/6100005
	trim() {
		local var="$*"
		# remove leading whitespace characters
		var="${var#"${var%%[![:space:]]*}"}"
		# remove trailing whitespace characters
		var="${var%"${var##*[![:space:]]}"}"
		printf '%s' "$var"
	}
	if type lexgrog > /dev/null 2>&1; then
	  local manPageText;
	  manPageText=$(lexgrog -w "$1")
	  if [[ $? -ne 0 ]]; then
		  echo "randomcowcommand: We messed up with $1" 1>&2
		  echo ""
		  return
	  fi
	  echo "$manPageText"| myshuf -n 1 | sed -E 's/^.*: "(.*)"$/\1/'
  else
	  #local manPageText="$(man -P cat $1)"
	  ## HACK(max): If you give `man` the path to the file, it won't correctly
	  # import `.so`s (because it `cd`s to the wrong directory for the relative
	  # imports to work).
	  # Workaround: do what `man FILEPATH` does, but in the right directory.
	  cd "$(dirname $1)"/..
	  local manPageText=$(zcat -f "$1" | mandoc)
	  local formatted_with_whitespace=$(echo "$manPageText" | col -bpx | grep "^NAME$" -A1 | tail -1)
	  local formatted=$(trim "$formatted_with_whitespace")
	  if [[ -z "$formatted" ]]; then
		  echo "randomcowcommand: We messed up with $1" 1>&2
	  fi
	  echo "$formatted"
  fi
}

format_message() {
  if type cowsay > /dev/null 2>&1; then
    cowsay -f "$(cowsay -l| tail -n+2|tr " " "\n"|sort -R|head -1)" "$1"
  else
    printf -- "\n-------------------------------\n"
    echo "Did you know: $1"
    printf -- '-------------------------------\n\n'
  fi
}

main() {
  if ! type manpath > /dev/null 2>&1; then
    echo "randomcowcommand - cannot run because manpath not installed" >&2
    exit 1
  fi
	manpagefile=$(find_random_manpage)
	commanddescription=$(get_description_of_manpage "$manpagefile")
	if [[ -z "$commanddescription" || "$commanddescription" == "builtin"*  ]]; then
		# we'll never get two duds in a row, right?
		manpagefile=$(find_random_manpage)
		commanddescription=$(get_description_of_manpage "$manpagefile")
	fi
	if [[ -z "$commanddescription" ]]; then
		# we'll never get three duds in a row, right?
		commanddescription="randomcowcommand - a script that works sometimes 😢\n"
	fi
	cow=$(format_message "$commanddescription")
	# download from github.com/arsham/rainbow
	if type rainbow 1>/dev/null 2>&1; then
		echo "$cow" | rainbow
	else
		echo "$cow"
	fi
}

# HACK(max): on my MacBook, `randomcowcommand` takes 200ms which is way too long.
# Instead, I'll get the cow in the background and save it to disk and then
# cat it here.
# The trick is that I'm always showing the _previous_ invocation of the
# cow.
if [[ ${1:-} == "--async" ]]; then
	cowtput=/tmp/cowtput.txt
	[[ -f $cowtput ]] && cat $cowtput || main
	# `disown` makes it not print a message when done
	# put this line after the `cat` to avoid a race condition where cowtput.txt
	# is empty because of the redirect
	(main 2>/dev/null 1> $cowtput) & disown
	# bug: if you run this command with --async many times in a row
	# (e.g. benchmarking with hyperfine) the outputs will overwrite each
	# other and be bad.  I don't care enough to fix this, because it'll
	# never realistically happen outside of benchmarks
else
	main
fi



# fun benchmark:
#
# ```sh
# hyperfine -w 2 \
# 	'find $(manpath -q | tr ":" " ") -type f -name "*.1" | myshuf -n 1' \
# 	'gfind $(manpath -q | tr ":" " ") -type f -name "*.1" | myshuf -n 1' \
# 	'fd \.1 $(manpath -q | tr ":" " ") --type=file | myshuf -n 1' \
# 	'OLDIFS=$IFS
# 	IFS=:
# 	for dir in $(manpath -q); do
# 		[[ -n $dir ]] && printf "%s\n" $dir/man1/* | grep -i perl
# 	done | myshuf -n 1
# 	IFS=$OLDIFS'
# 	'
# 	OLDIFS=$IFS
# 	IFS=:
# 	for dir in $(manpath -q); do
# 		[[ -n $dir ]] && fd --exact-depth=2 . $dir/ | grep -i perl
# 	done | myshuf -n 1
# 	IFS=$OLDIFS
# 	'
#```
