#!/bin/bash

set -u

step=all

cd "$(dirname "$0")"/.. || exit 1

difs () {
    ref=$1
    declare -i errs=0
    for f in tests/*.input.txt; do
        name="$(basename "${f%.input.txt}")"
        [[ ${name} = *${namefilter}* ]] || continue
        dif1 "${ref}" "${name}" || (( errs++ ))
    done
    return ${errs}
}
wdif () {
    colorspec=$1
    if command -V dwdiff &>/dev/null; then
        dwdiff --color="${colorspec}" --diff-input
    else
        cat
    fi
}
dif1 () {
    ref=$1
    name=$2
    case ${ref} in
        expected) colorspec=green,bcyan
                  reffile=tests/out/"${name}.${step}".expected.txt ;;
        gold) colorspec=brown,bcyan
              reffile=tests/"${name}.${step}".gold.txt ;;
        *)
            echo "ERROR bug in call to dif1" >&2; exit 1 ;;
    esac
    (
        set -o pipefail
        diff -U0 -I'^nno-nob\|AP_SRC'                  \
             "${reffile}"                              \
             tests/out/"${name}"."${step}".current.txt \
            | wdif "${colorspec}"
    )
}

assert-translated () {
    for f in tests/*.input.txt; do
        name="$(basename "${f%.input.txt}")"
        [[ ${name} = *${namefilter}* ]] || continue
        cur=tests/out/"${name}"."${step}".current.txt
        if [[ ! -f "${cur}" ]]; then
            echo "${cur} not found" >&2
            echo >&2
            echo "Please run '$0 translate' first" >&2
            exit 1
        fi
    done
}

assert-usage () {
    echo "USAGE:

$0 translate      # run this after your edits and compiles
$0 diff-expected  # compare result of 'translate' with expected output
$0 diff-gold      # compare result of 'translate' with gold set
$0 update         # update the current expected output with result of 'translate'
$0 expect         # add sentence from stdin as new test with current as expected
"
    exit 1
}

get-mode () {
    # TODO: Get mode from file name (but need an unambiguous file name scheme then)
    if [[ $1 = *cappelen* ]]; then
        echo nob-nno
    else
        echo nob-nno_e
    fi
}

setvars () {
    if [[ $1 = *cappelen* ]]; then
        # shellcheck source=./cappelen
        source t/cappelen
    else
        export AP_SETVAR=''
    fi
}

[[ $# -lt 1 || $# -gt 2 ]] && assert-usage

namefilter=''
[[ $# -ge 2 ]] && namefilter=$2

case $1 in
    translate)
        for f in tests/*.input.txt; do
            name="$(basename "${f%.input.txt}")"
            [[ ${name} = *${namefilter}* ]] || continue
            mode=$(get-mode "${name}")
            setvars "${name}"
            apertium -d . "${mode}" < tests/"${name}".input.txt >tests/out/"${name}.${step}".current.txt
        done
        ;;
    update)
        assert-translated "${namefilter}"
        for cur in tests/out/*."${step}".current.txt; do
            cp -v "${cur}" "${cur%current.txt}expected.txt"
        done
        ;;
    diff-expected)
        assert-translated "${namefilter}"
        difs expected "${namefilter}"
        ;;
    diff-gold)
        assert-translated "${namefilter}"
        difs gold "${namefilter}"
        ;;
    expect)
        if [[ -z "${namefilter}" ]]; then echo "Needs a test set, e.g. 'ymse'"; exit 1; fi
        seen=false
        for f in tests/*.input.txt; do
            name="$(basename "${f%.input.txt}")"
            [[ ${name} = *${namefilter}* ]] || continue
            mode=$(get-mode "${name}")
            setvars "${name}"
            expf=tests/out/"${name}".all.expected.txt
            goldf=tests/"${name}".all.gold.txt
            input=$(cat)
            [[ "${input}" = *[.?\!] ]] || input="${input}." # ensure final punctuation
            echo "${input}" | tee -a "${f}" | apertium -d . "${mode}" | tee -a "${expf}" "${goldf}"
            seen=true
            break
        done
        if ! ${seen}; then echo "Unknown test set '${namefilter}'"; echo "(couldn't find file matching tests/*${namefilter}*.input.txt – try 'ymse' if unsure)"; exit 1; fi
        ;;
    *)
        assert-usage
        ;;
esac
