#!/bin/sh

# Main ├────────────────────────────────────────────────────────────────────────

main() {
  number_tests=0
  number_failures=0
  dirs="${@:-.}"
  test=$(pwd)
  work=$(mktemp -d /tmp/kak-tests.XXXXXXXX)
  cp -R . $work
  trap "rm -R $work" EXIT
  for dir in $(find $dirs -type d | sort); do
    cd $test/$dir;
    test_files=$(ls out selections state display 2>/dev/null)
    cd $work/$dir;
    indent="$(echo "${dir}/" | sed -e 's|[^/]*/\+|  |g')"
    name=$(basename $PWD)
    should_fail=$(test ! -e error; echo $?)
    if ! test -e cmd; then
      echo "$indent$name"
    elif test -x enabled && ! ./enabled; then
      echo "$indent$name (disabled)" | colorize yellow normal
    else
      number_tests=$(($number_tests + 1))
      touch in; cp in out
      kak_commands="
        set global autoreload yes
        set global autoinfo ''
        set global autoshowcompl false
        try %{
          source rc
        }
        try %{
          exec '%s%\(\K[^)]+<ret><c-s>ld<a-t>(hHdi<c-u><esc><c-o>'
        } \
        catch %{
          exec gg
        }
        hook global RuntimeError .+ %{
          nop %sh{echo \"\$kak_hook_param\" > stderr}
          quit!
        }
        exec '$(cat cmd | sed -e s/\'/\\\\\'/g)'
        exec <c-l>
        eval -buffer *debug* write debug
        nop %sh{
          IFS==
          echo \"\$kak_selections\"      > selections
          echo \"\$kak_selections_desc\" > state
        }
        write out
        quit!
      "
      session="kak-test-$(printf '%s' "$dir" | sed -e 's+^\./++; s+/+-+g')"
      rm -f /tmp/kakoune/$USER/$session
      ${test}/../src/kak out -n -s "$session" -ui json -e "$kak_commands" > display
      retval=$?
      if [ $should_fail -eq 0 ]; then
        if [ $retval -ne 0 ]; then
          echo "Kakoune returned error $retval"
          number_failures=$(($number_failures + 1))
          echo "$indent$name" | colorize red normal
        else
          failed=no
          for expect in $test_files; do
            if ! cmp -s $test/$dir/$expect $expect; then
              if [ "$failed" = no ]; then
                echo "$indent$name" | colorize red normal
                failed=yes
              fi
              echo
              diff -u $test/$dir/$expect $expect | while read -r line; do
                first_character=$(echo "$line" | cut -b 1)
                case $first_character in
                  +) color=green ;;
                  -) color=red ;;
                  @) color=magenta ;;
                  *) color=none ;;
                esac
                echo "$line" | colorize $color normal
              done
            fi
          done
          if [ "$failed" = no ]; then
            echo "$indent$name" | colorize green normal
          else
            number_failures=$(($number_failures + 1))
            echo
            if test -e debug; then
              echo "debug buffer:" | colorize yellow normal
              cat debug
              echo
            fi
          fi
        fi
      else
        color=green
        if [ ! -e stderr ]; then
          if [ $retval -eq 0 ]; then
            color=red
            number_failures=$(($number_failures + 1))
          fi
        else
            sed -ri 's/^[0-9]+:[0-9]+: //g' stderr
            if [ -s error ] && ! cmp -s error stderr; then
              color=yellow
            fi
        fi

        echo "$indent$name" | colorize $color normal
      fi
    fi
  done
  if expr $number_failures > 0; then
    color=red
  else
    color=green
  fi
  echo
  echo Resume:
  echo $number_tests tests, $number_failures failures | colorize $color normal
  exit $number_failures
}

# Utility ├─────────────────────────────────────────────────────────────────────

get_ansi_code() {
  color_name=${1:-none}
  style_name=${2:-none}
  case "$color_name" in
    none)    color_nr=00 ;;
    red)     color_nr=31 ;;
    green)   color_nr=32 ;;
    yellow)  color_nr=33 ;;
    magenta) color_nr=35 ;;
    *)       color_nr=00 ;;
  esac
  case "$style_name" in
    none) style_nr=00 ;;
    bold) style_nr=01 ;;
    *)    style_nr=00 ;;
  esac
  printf '\033[%s;%sm' $style_nr $color_nr
}

colorize() {
  text=$(cat)
  color_name=${1:-none}
  style_name=${2:-none}
  echo "$(get_ansi_code $color_name $style_name)$text$(get_ansi_code none none)"
}


main $@