#!/usr/bin/env bash
set -e

# Just stream the TAP output (sans extended syntax) if tput is missing
command -v tput >/dev/null || exec grep -v "^begin "

header_pattern='[0-9]+\.\.[0-9]+'
IFS= read -r header

if [[ "$header" =~ $header_pattern ]]; then
  count="${header:3}"
  index=0
  failures=0
  skipped=0
  name=""
  count_column_width=$(( ${#count} * 2 + 2 ))
else
  # If the first line isn't a TAP plan, print it and pass the rest through
  printf "%s\n" "$header"
  exec cat
fi

update_screen_width() {
  screen_width="$(tput cols)"
  count_column_left=$(( $screen_width - $count_column_width ))
}

trap update_screen_width WINCH
update_screen_width

begin() {
  go_to_column 0
  printf_with_truncation $(( $count_column_left - 1 )) "   %s" "$name"
  clear_to_end_of_line
  go_to_column $count_column_left
  printf "%${#count}s/${count}" "$index"
  go_to_column 1
}

pass() {
  go_to_column 0
  printf " ✓ %s" "$name"
  advance
}

skip() {
  local reason="$1"
  [ -z "$reason" ] || reason=": $reason"
  go_to_column 0
  printf " - %s (skipped%s)" "$name" "$reason"
  advance
}

fail() {
  go_to_column 0
  set_color 1 bold
  printf " ✗ %s" "$name"
  advance
}

log() {
  set_color 1
  printf "   %s\n" "$1"
  clear_color
}

summary() {
  printf "\n%d test%s" "$count" "$(plural "$count")"

  printf ", %d failure%s" "$failures" "$(plural "$failures")"

  if [ "$skipped" -gt 0 ]; then
    printf ", %d skipped" "$skipped"
  fi

  printf "\n"
}

printf_with_truncation() {
  local width="$1"
  shift
  local string="$(printf "$@")"

  if [ "${#string}" -gt "$width" ]; then
    printf "%s..." "${string:0:$(( $width - 4 ))}"
  else
    printf "%s" "$string"
  fi
}

go_to_column() {
  local column="$1"
  printf "\x1B[%dG" $(( $column + 1 ))
}

clear_to_end_of_line() {
  printf "\x1B[K"
}

advance() {
  clear_to_end_of_line
  echo
  clear_color
}

set_color() {
  local color="$1"
  local weight="$2"
  printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )"
}

clear_color() {
  printf "\x1B[0m"
}

plural() {
  [ "$1" -eq 1 ] || echo "s"
}

_buffer=""

buffer() {
  _buffer="${_buffer}$("$@")"
}

flush() {
  printf "%s" "$_buffer"
  _buffer=""
}

finish() {
  flush
  printf "\n"
}

trap finish EXIT

while IFS= read -r line; do
  case "$line" in
  "begin "* )
    let index+=1
    name="${line#* $index }"
    buffer begin
    flush
    ;;
  "ok "* )
    skip_expr="ok $index # skip (\(([^)]*)\))?"
    if [[ "$line" =~ $skip_expr ]]; then
      let skipped+=1
      buffer skip "${BASH_REMATCH[2]}"
    else
      buffer pass
    fi
    ;;
  "not ok "* )
    let failures+=1
    buffer fail
    ;;
  "# "* )
    buffer log "${line:2}"
    ;;
  esac
done

buffer summary