#!/usr/bin/env bash

wait-n-failure::main () {

  local explicit_pids='false'
  local monitor='false'
  local notify='false'
  local posix='false'
  
  local arg
  for arg in "${@}"; do
    case "${arg}" in
    ( 'explicit_pids' )
      explicit_pids='true'
    ;;
    ( 'monitor' )
      monitor='true'
    ;;
    ( 'notify' )
      notify='true'
    ;;
    ( 'posix' )
      posix='true'
    ;;
    esac
  done

  printf '%s\n' "explicit_pids ${explicit_pids}"
  printf '%s\n' "monitor ${monitor}"
  printf '%s\n' "notify ${notify}"
  printf '%s\n' "posix ${posix}"

  printf 'bash %s\n' "${BASH_VERSION}"

  local -
  set -o nounset -o noglob +o braceexpand
  if [[ ${monitor} == 'true' ]]; then
    set -o monitor
  else
    set +o monitor
  fi
  if [[ ${notify} == 'true' ]]; then
    set -o notify
  else
    set +o notify
  fi
  if [[ ${posix} == 'true' ]]; then
    set -o posix
  else
    set +o posix
  fi

  local -a pid_set
  SECONDS=0

  wait-n-failure::random_sleep &
  pid_set[${!}]=''
  wait-n-failure::random_sleep &
  pid_set[${!}]=''
  wait-n-failure::random_sleep &
  pid_set[${!}]=''
  wait-n-failure::random_sleep &
  pid_set[${!}]=''
  wait-n-failure::random_sleep &
  pid_set[${!}]=''

  local -i processes_forked=5
  local -i processes_waited=0

  local terminated_pid
  local success
  while
    {
      (( processes_forked < 100 )) ||
        {
          success='true'
          false
        }
      #
    } &&
      {
        if [[ ${explicit_pids} == 'true' ]]; then
          wait -n -p terminated_pid -- "${!pid_set[@]}"
        else
          wait -n -p terminated_pid
        fi ||
          {
            success='false'
            false
          }
        #
      }
    #
  do
    unset pid_set[${terminated_pid}]
    (( ++processes_waited ))
    wait-n-failure::random_sleep &
    pid_set[${!}]=''
    (( ++processes_forked ))
    wait-n-failure::random_sleep
  done
  if [[ ${success} == 'true' ]]; then
    while
      (( ${#pid_set[@]} > 0 )) &&
        if [[ ${explicit_pids} == 'true' ]]; then
          wait -n -p terminated_pid -- "${!pid_set[@]}"
        else
          wait -n -p terminated_pid
        fi
      #
    do
      unset pid_set[${terminated_pid}]
      (( ++processes_waited ))
    done
  fi
  printf '%s processes waited / %s processes forked\n' "${processes_waited}" "${processes_forked}"
  printf '%s seconds\n' "${SECONDS}"

}

wait-n-failure::random_sleep () {
  local random
  printf -v random '%03d' "${SRANDOM}"
  sleep -- "0.0${random: -3}"
}

run='false'
for arg in "${@}"; do
  if [[ ${arg} == 'run' ]]; then
    run='true'
  fi
done
printf '%s\n' "run ${run}"
if [[ ${run} == 'true' ]]; then
  wait-n-failure::main "${@}"
  unset wait-n-failure::main wait-n-failure::random_sleep
fi
unset run arg
