#!/bin/bash -e

#####################################################################
#                                                                   #
#                    faust2daisy generator                          #
#                       (c) Grame, 2020                             #
#                                                                   #
#####################################################################

. faustpath
. faustoptflags
. usage.sh

CXXFLAGS+=" $MYGCCFLAGS"  # So that additional CXXFLAGS can be used
C_INCLUDES="-I $FAUSTINC"
ARCHFILE=$FAUSTARCH/daisy/ex_faust.cpp

# exit if a command fails
set -e

# global option variables
NVOICES=0
MIDI=false
POLY=""
PATCH=false
POD=false
PATCHSM=false
USE_SDRAM=false
SR=44100
BS=16
SOURCE=false
APP_TYPE=BOOT_NONE
MEM_THRESH=64

echoHelp ()
{
    echo "faust2daisy [-patch] [-sram] [-qspi] [-sdram] [-mem-thresh] [-midi] [-nvoices <num>] [-sr <num>] [-bs <num>] [-source] [Faust options (-vec -vs 8...)] <file.dsp>"
    echo "Compiles Faust programs to Daisy boards (see https://github.com/grame-cncm/faust/tree/master-dev/architecture/daisy)"
    option
    option -sram "flashing to sram (medium sized programs), requires daisy bootloader"
    option -qspi "flashing to qspi memory (biggest programs), requires daisy bootloader"
    option -patch "to compile for 4 ins/outs Patch (knob[1,2,3,4])"
    option -pod "to compile for 2 ins/outs Pod (knob[1,3])"
    option -patchsm "to compile for the patch.Init() eurorack module"
    option -sdram "to compile using SDRAM for long delay lines/tables etc."
    option "-mem-thresh <num>" "Memory threshold in bytes above which data is stored on SDRAM, requires -sdram"
    options -midi
    option "-nvoices <num>"
    option "-sr <num>"
    option "-bs <num>"
    option -source
    option "Faust options"
    echo ""
    exit
}

if [ "$#" -eq 0 ]; then
    echo 'Please, provide a Faust file to process !'
    echo ''
    echoHelp
fi

###########################
# Processing Arguments
###########################

while [ $1 ]
do
    p=$1
    # help
    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echoHelp
    # -nvoices:
    elif [ $p = "-sram" ]; then 
        APP_TYPE=BOOT_SRAM
        USE_SDRAM=true # Because SRAM is used, SDRAM is necessary for data 
    elif [ $p = "-qspi" ]; then 
        APP_TYPE=BOOT_QSPI
    elif [ $p = "-nvoices" ]; then
        shift
        NVOICES=$1
    # -midi
    elif [ $p = "-midi" ]; then
        MIDI=true
    #patch
    elif [ $p = "-patch" ]; then
        PATCH=true
    elif [ $p = "-pod" ]; then
        POD=true
    elif [ $p = "-patchsm" ]; then
        PATCHSM=true
    # -sdram
    elif [ $p = "-sdram" ]; then
        USE_SDRAM=true
    elif [ $p = "-mem-thresh" ]; then 
        shift
        MEM_THRESH=$1 
    # -sr
    elif [ $p = "-sr" ]; then
        shift
        SR=$1
    # -bs
    elif [ $p = "-bs" ]; then
        shift
        BS=$1
    # -source
    elif [  $p = "-source" ]; then
        SOURCE=true
    elif [[ -f "$p" ]]; then
        FILE="$p"
    # other compile options
    else
        OPTIONS="$OPTIONS $p"
    fi

shift
done

###########################
# Compile the *.dsp files
###########################

for p in $FILE; do
    CUR=$(pwd)
    f=$(basename "$p")
    SRCDIR=$(dirname "$p")

    # creates the dir
    dspName="${f%.dsp}"
    rm -rf "$SRCDIR/$dspName"
    mkdir "$SRCDIR/$dspName"

    MEM_THRESH_UNIT=$(($MEM_THRESH/4))
    # compile faust to c++
    cp -r "$FAUSTARCH/daisy/Makefile" "$SRCDIR/$dspName/"
    if [ $USE_SDRAM == true ]; then 
        faust -i -a "$ARCHFILE" $OPTIONS "$f" -json -mem1 -it -fpga-mem-th $MEM_THRESH_UNIT -o "$SRCDIR/$dspName/ex_faust.cpp" || exit
        NVOICES=$(python3 "$FAUSTARCH/daisy/faust_daisy_mem.py" "$SRCDIR/$dspName" $MEM_THRESH $NVOICES 1)
    else 
        faust -i  -a "$ARCHFILE" $OPTIONS "$f" -json -o "$SRCDIR/$dspName/ex_faust.cpp" || exit
        NVOICES=$(python3 "$FAUSTARCH/daisy/faust_daisy_mem.py" "$SRCDIR/$dspName" $MEM_THRESH $NVOICES 0)
    fi

    # for PATCH support
    if [ $PATCH == true ]; then
        echo "#define PATCH" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi
    # for POD support
    if [ $POD == true ]; then
        echo "#define POD" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi
    # for PODSM support
    if [ $PATCHSM == true ]; then
        echo "#define PATCHSM" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi

    # for POLY
    if [ "$NVOICES" > 0 ]; then
        MIDI=true
        echo "Setting Nvoices $NVOICES"
        echo "#define POLY" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
        echo "#define NVOICES $NVOICES" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi

    # for MIDI
    if [ $MIDI == true ]; then
        echo "#define MIDICTRL" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi
    
    if [ $USE_SDRAM == true ]; then
        echo "#define USE_SDRAM" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"
    fi

    # for Sample Rate
    echo "#define MY_SAMPLE_RATE $SR" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"

    # for Buffer Size
    echo "#define MY_BUFFER_SIZE $BS" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"

    # for DAISY_NO_RTTI preprocessor flag (to avoid dynamic casts since libdaisy is compiled with -fno-rtti flag)
    echo "#define DAISY_NO_RTTI" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp"


    #if [ $USE_SDRAM == true ]; then
        #python3 "$FAUSTARCH/daisy/faust_sdram_converter.py" "$SRCDIR/$dspName/ex_faust.cpp"
    #fi

    # compile and install plugin or keep the source folder
    if [ $SOURCE == false ]; then
        export $APP_TYPE
        cd "$SRCDIR/$dspName"
        pwd
        echo "Building Faust program"
        (make APP_TYPE=$APP_TYPE) || exit 

        if [ $APP_TYPE == BOOT_NONE ]; then 
            read -p "Press ENTER when Daisy is in DFU mode"
            (make program-dfu)  || true
        else 
            read -r -p "Do you want to flash Daisy bootloader ? [y/n] : " response
            case "$response" in 
                [yY])
                    read -p "Press ENTER when Daisy is in DFU mode to flash bootloader"
                    (make program-boot) || true 
                    sleep 1s # Make sure bootloader is operational
                ;;
                *)
            esac
            read -p "Press Daisy RESET button, then press ENTER (approximately 1 sec after RESET)" 
            (make program-dfu APP_TYPE=$APP_TYPE)  || true 
        fi

        cd ..
        #rm -rf "$SRCDIR/$dspName"
        echo "Success !"
    else
        echo "Create the $SRCDIR/$dspName folder"
    fi
done
