#!/bin/sh

PATH=../../build/bin:$PATH
faust --version || exit $?
echo location $(command -v faust)

# detect the current system
system=$(uname -s)
# normalizes MINGW versions
system=$(echo $system | grep MINGW > /dev/null && echo MINGW || echo $system)

## manual exclusion list
: ${TESTS_EXCLUDED:=}
## exclusion list for faust errors
: ${XLIST1}="faust2md"

if [ "$system" = "Darwin" ]; then
    TESTS="faust2android faust2au faust2caqt faust2csound faust2faustvst faust2jack faust2jaqt faust2max6 faust2msp faust2puredata faust2supercollider faust2unity faust2vst faust2vsti faust2ios faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_MIDI="faust2caqt faust2jack faust2jaqt faust2max6 faust2msp faust2ios faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLY="faust2caqt faust2jack faust2jaqt faust2max6 faust2msp faust2ios faust2juce faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLYMIDI="faust2caqt faust2jack faust2jaqt faust2max6 faust2msp faust2ios faust2juce faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLY2MIDI="faust2caqt faust2ios faust2max6 faust2msp faust2juce faust2netjackconsole faust2netjackqt"
    TESTS_SOUND="faust2caqt faust2jaqt faust2jack faust2ios faust2max6 faust2msp"
    TESTS_HTTPD="faust2caqt faust2jack faust2jaqt faust2jackconsole faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_OSC="faust2ios faust2caqt faust2jack faust2jaqt faust2jackconsole faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_OSCHTTPD="faust2caqt faust2jack faust2jaqt faust2jackconsole faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_APIS="-ios"
elif [ "$system" = "Linux" ]; then
    TESTS="faust2alqt faust2alsa faust2alsaconsole faust2android faust2asmjs faust2bela faust2csound faust2dssi faust2eps faust2faustvst faust2firefox faust2graph faust2graphviewer faust2jack faust2jackinternal faust2jackserver faust2jaqt faust2ladspa faust2lv2 faust2mathdoc  faust2md  faust2netjackconsole faust2netjackqt faust2octave faust2owl faust2paqt faust2pdf faust2plot faust2png faust2puredata faust2raqt faust2ros faust2rosgtk faust2rpialsaconsole faust2rpinetjackconsole faust2sig faust2sigviewer faust2supercollider faust2svg faust2w32max6 faust2w32msp faust2w32puredata faust2w32vst faust2w64vst faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_MIDI="faust2jaqt faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLY="faust2jaqt faust2juce faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLYMIDI="faust2jaqt faust2juce faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_POLY2MIDI=""
    TESTS_SOUND=""
    TESTS_HTTPD=""
    TESTS_OSC=""
    TESTS_OSCHTTPD="faust2jaqt faust2netjackconsole faust2netjackqt faust2jackconsole"
    TESTS_APIS="-android"
fi

## test exclusion : notinlist "toto" "a b c d e"
notinlist() {
    for word in $2; do
        if [ $word = $1 ]; then
            return 1
        fi
    done
    return 0
}

## get all the items that are in list A but not in list B
##  listexclude $A $B $B
listexclude() {
    for w in "$@"; do
        echo $w
    done | sort | uniq -u
}

runtest() {
    # usage: runtest <logfile> <cmd> <arg1> ...
    local logfile=$1
    shift
    ("$@" >"${logfile}" 2>&1) && echo "OK: '$@' succeeded!" || echo "ERROR: '$@' failed"
    rm -rf good
}

runtestfail() {
    # usage: runtestfail <logfile> <cmd> <arg1> ...
    local logfile=$1
    shift
    ("$@" >"${logfile}" 2>&1) && echo "ERROR: '$@' shouldn't have succeeded!" || echo "OK: '$@' correctly failed"
    rm -rf good
}

runtestref() {
    # usage: runtestref <logfile> <name> <refbasename> <cmd> <arg1>...
    local logfile=$1
    local name=$2
    local referencefile="${3}_ref.txt"
    local resultfile="${3}.txt"
    shift 3
    if ("$@" >"${logfile}" 2>&1); then
        "./${name}" > "${resultfile}"
        diff "${resultfile}" "${referencefile}" && echo "OK: '$@' succeeded!" || echo "ERROR: '$@' failed (mismatched output)"
    else
        echo "ERROR: '$@' failed"
    fi
    rm -f "${resultfile}"
    rm -rf "${name}"
}

if [ "x${TESTS}" != x ]; then
    # strip away any tests listed in TESTS_EXCLUDED
    # as a side-effect, this sorts the tests alphabetically
    TESTS=$(listexclude ${TESTS} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_MIDI=$(listexclude ${TESTS_MIDI} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_POLY=$(listexclude ${TESTS_POLY} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_POLYMIDI=$(listexclude ${TESTS_POLYMIDI} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_POLY2MIDI=$(listexclude ${TESTS_POLY2MIDI} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_SOUND=$(listexclude ${TESTS_SOUND} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_HTTPD=$(listexclude ${TESTS_HTTPD} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_OSC=$(listexclude ${TESTS_OSC} $TESTS_EXCLUDED $TESTS_EXCLUDED)
    TESTS_OSCHTTPD=$(listexclude ${TESTS_OSCHTTPD} $TESTS_EXCLUDED $TESTS_EXCLUDED)

    echo "------------------------"
    echo Run tests for $system with renamed class and superclass
    echo "------------------------"

    echo "Test: "${TESTS:-<none>}
    echo "Test '-midi':" ${TESTS_MIDI:-<none>}
    echo "Test '-nvoices 8':" ${TESTS_POLY:-<none>}
    echo "Test '-nvoices 8 -midi':" ${TESTS_POLYMIDI:-<none>}
    echo "Test '-nvoices 8 -effect <foo.dsp> -midi':" ${TESTS_POLY2MIDI:-<none>}
    echo "Test '-soundfile':" ${TESTS_SOUND:-<none>}
    echo "Test '-httpd':" ${TESTS_HTTPD:-<none>}
    echo "Test '-osc':" ${TESTS_OSC:-<none>}
    echo "Test '-osc -httpd':" ${TESTS_OSCHTTPD:-<none>}

    for scriptname in ${TESTS}; do
        for RENAME in "" "-cn Bidule" "-cn Bidule -scn Machin"; do
            runtest LOG "${scriptname}" ${RENAME} good.dsp
        done
    done

    for scriptname in ${TESTS_MIDI}; do
        for RENAME in "" "-cn Bidule" "-cn Bidule -scn Machin"; do
            runtest LOG "${scriptname}" ${RENAME} -midi good.dsp
        done
    done

    for scriptname in ${TESTS_POLY}; do
        for RENAME in "" "-cn Bidule" "-cn Bidule -scn Machin"; do
            runtest LOG "${scriptname}" ${RENAME} -nvoices 8 good.dsp
        done
    done

    for scriptname in ${TESTS_POLYMIDI}; do
        for RENAME in "" "-cn Bidule" "-cn Bidule -scn Machin"; do
            runtest LOG "${scriptname}" ${RENAME} -nvoices 8 -midi good.dsp
        done
    done

    for RENAME in "" "-cn Bidule" "-cn Bidule -scn Machin"; do
        for scriptname in ${TESTS_POLY2MIDI}; do
            runtest LOG "${scriptname}" ${RENAME} -nvoices 8 -effect good.dsp -midi good.dsp
        done

        for scriptname in ${TESTS_SOUND}; do
            runtest LOG "${scriptname}" ${RENAME} -soundfile -lang ocpp sound.dsp
        done

        for scriptname in ${TESTS_SOUND}; do
            runtest "${scriptname}" ${RENAME} -soundfile sound.dsp
        done

        # not on linux?
        runtest LOG faust2juce ${RENAME} -soundfile -standalone sound.dsp

        for scriptname in ${TESTS_HTTPD}; do
            runtest LOG "${scriptname}" ${RENAME} -httpd good.dsp
        done

        for scriptname in ${TESTS_OSC}; do
            runtest "${scriptname}" ${RENAME} -osc good.dsp
        done

        for scriptname in ${TESTS_OSCHTTPD}; do
            runtest "${scriptname}" ${RENAME} -osc -httpd good.dsp
        done

        for api in ${TESTS_APIS}; do
            runtest LOG faust2api ${RENAME} "${api}" good.dsp
            runtest LOG faust2api ${RENAME} "${api}" -midi good.dsp
            runtest LOG faust2api ${RENAME} "${api}" -midi -nvoices 8 good.dsp
            runtest LOG faust2api ${RENAME} "${api}" -nvoices 8 -effect effect.dsp -midi good.dsp

            if [  "x${api}" = "x-ios" ]; then
                runtest LOG faust2api ${RENAME} "${api}" -soundfile -lang ocpp sound.dsp
                runtest LOG faust2smartkeyb ${RENAME} "${api}" good.dsp
                runtest LOG faust2smartkeyb ${RENAME} "${api}" -osc good.dsp
                runtest LOG faust2smartkeyb ${RENAME} "${api}" -osc -midi good.dsp
                runtest LOG faust2smartkeyb ${RENAME} "${api}" -osc -midi -nvoices 8 good.dsp
                runtest LOG faust2smartkeyb ${RENAME} "${api}" -effect effect.dsp -nvoices 8 good.dsp
            fi
        done

        if [ "$system" = "Darwin" ]; then
            runtest LOG faust2nodejs ${RENAME} -coreaudio good.dsp
            runtest LOG faust2nodejs ${RENAME} -coreaudio -midi good.dsp
            runtest LOG faust2nodejs ${RENAME} -coreaudio -midi -nvoices 8 good.dsp
            #runtest LOG faust2nodejs -coreaudio -nvoices 8 -effect effect.dsp -midi good.dsp
        fi

        # Test of -exp10
        runtest LOG faust2jack ${RENAME} -exp10 exp10.dsp
        runtestfail LOG faust2android ${RENAME} -exp10 exp10.dsp
        runtestref LOG good good faust2dummy ${RENAME} good.dsp
        runtestref LOG good good faust2dummy ${RENAME} -midi good.dsp
        runtestref LOG organ organ_2voices faust2dummy ${RENAME} -midi -nvoices 2 organ.dsp
        runtestref LOG organ organ_8voices faust2dummy ${RENAME} -midi organ.dsp
        runtestref LOG waveform4 waveform4 faust2dummymem ${RENAME} waveform4.dsp
    done
elif [ "$system" = "MINGW" ]; then
    echo "not yet implemented"
else
    echo
    echo "Test all Faust2xxx to work"
    echo
    for scriptname in $(listexclude $(for S in ../../tools/faust2appls/faust2*; do echo $(basename "$S" .in); done) ${XLIST1} ${XLIST1} ${TESTS_EXCLUDED} ${TESTS_EXCLUDED}); do
        runtest LOG "${scriptname}" good.dsp
    done
fi
