#!/bin/bash -e

. faustpath
. usage.sh

#FAUST DATA:
[ -z "$ARCHFILE" ] && ARCHFILE=$FAUSTARCH/bela.cpp
#BELA DATA:
[ -z "$BBB_ADDRESS" ] && BBB_ADDRESS="root@192.168.7.2"
[ -z "$BBB_BELA_HOME" ] && BBB_BELA_HOME="/root/Bela"
[ -z "$BBB_PROJECT_HOME" ] && BBB_PROJECT_HOME="${BBB_BELA_HOME}/projects/"
[ -z "$BELA_CPPFLAGS" ] && BELA_CPPFLAGS=""
[ -z "$BELA_LDLIBS" ] && BELA_LDLIBS=""

BELA_CPPFLAGS="$BELA_CPPFLAGS"

#variables:
NVOICES=0
POLY=""
EFFECT=""
MIDIDEFS=""
OSCDEFS=""
SEND2BELA=""
OPTIONS=""

echoHelp() 
{
    usage faust2bela "[options] [Faust options] <file.dsp>"
    platform Bela
    echo "Compiles Faust programs to the BELA board"
    option
    options -osc -midi -soundfile
    option "-nvoices <num>"
    echo "Polyphonic mode means MIDI instrument with at least 1 voice. Use no arguments for a simple effect."
    option -gui "activates a self-hosted GUI interface. Requires to have libmicrohttpd and libHTTPDFaust installed."
    option "-effect <effect.dsp>" "generates a polyphonic DSP connected to a global output effect, ready to be used with MIDI"
    option "-effect auto" "generates a polyphonic DSP connected to a global output effect defined as 'effect' in <file.dsp>, ready to be used with MIDI"
    option -tobela "to send C++ file into bela, and to run it"
    option "Faust options"
    exit
}

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

#-------------------------------------------------------------------
#PHASE 1 : dispatch command arguments
#-------------------------------------------------------------------
while [ $1 ]
do
    p=$1

    # HELP:
    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echoHelp
    # -NVOICES:
    elif [ $p = "-nvoices" ]; then
        shift
        NVOICES=$1
    # -EFFECT:
    elif [ $p = "-effect" ]; then
        POLY="POLY2"
        shift
        EFFECT=$1
    # -MIDI
    elif [ $p = "-midi" ]; then
        MIDIDEFS="MIDI"
    elif [ $p = "-osc" ]; then
        OSCDEFS="OSC"
    elif [ $p = "-gui" ]; then
        GUIDEFS="GUI"
    elif [ $p = "-soundfile" ]; then
        SOUNDFILEDEFS="SOUNDFILE"
    elif [ $p = "-tobela" ]; then
        SEND2BELA="OK"
    else
        OPTIONS="$OPTIONS $p"
    fi

shift

done
#-------------------------------------------------------------------
#PHASE 2 : compile the *.dsp files
#-------------------------------------------------------------------

CUR=$(pwd)
f=$(basename "$p")
SRCDIR=$(dirname "$p")
INPUT_FILE="$SRCDIR/$f"

# creates a dir
TMP="${f%.dsp}"
mkdir -p "$TMP/tmp"

PROJECTDIR="$CUR/$TMP"
FAUST_MAIN_OUTPUT=$TMP/tmp/rendertmp.cpp
# compile faust to c++
faust $FAUST_ARGS -i -a $ARCHFILE $OPTIONS "$INPUT_FILE" -o "$FAUST_MAIN_OUTPUT"

EFFECT_OUTPUT=$TMP/effect.h
if [[ "$POLY" == *POLY2* ]]; then
    if [ $EFFECT = "auto" ]; then
        # Creer un fichier .dsp simple
        cat > $TMP/effect.dsp << EndOfCode
        adapt(1,1) = _;
        adapt(2,2) = _,_;
        adapt(1,2) = _ <: _,_;
        adapt(2,1) = _,_ :> _;

        adaptor(F,G) = adapt(outputs(F),inputs(G));

        process = adaptor(library("$INPUT_FILE").process, library("$INPUT_FILE").effect) : library("$INPUT_FILE").effect;
EndOfCode
        faust $FAUST_ARGS -i -cn effect -a minimal-effect.cpp "$TMP/effect.dsp" -o "$EFFECT_OUTPUT"

    else
        faust $FAUST_ARGS -i -cn effect -a minimal-effect.cpp "$EFFECT" -o "$EFFECT_OUTPUT"
    fi
fi

#-------------------------------------------------------------------
#PHASE 3 : Data for BELA
#-------------------------------------------------------------------

echo '// Options :' > "$PROJECTDIR/tmp.txt"
if [ $NVOICES -gt 0 ]; then
    echo '#define NVOICES '$NVOICES >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$MIDIDEFS" == *MIDI* ]]; then
    echo '#define MIDICTRL' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$POLY" == *POLY2* ]]; then
    echo '#define POLY2' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$OSCDEFS" == *OSC* ]]; then
    echo '#define OSCCTRL' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$GUIDEFS" == *GUI* ]]; then
    echo '#define HTTPDGUI' >> "$PROJECTDIR/tmp.txt"
    BELA_LDLIBS="$BELA_LDLIBS -lHTTPDFaust -lmicrohttpd"
fi

if [[ "$SOUNDFILEDEFS" == *SOUNDFILE* ]]; then
    echo '#define SOUNDFILE' >> "$PROJECTDIR/tmp.txt"
    BELA_LDLIBS="$BELA_LDLIBS -lsndfile"
fi

cat "$FAUST_MAIN_OUTPUT" >> "$PROJECTDIR/tmp.txt"
mv "$PROJECTDIR/tmp.txt" "$PROJECTDIR/render.cpp"
rm -rf "$PROJECTDIR/tmp"

#-------------------------------------------------------------------
#PHASE 4 : SEND data to BELA and RUN it.
#-------------------------------------------------------------------

if [[ "$SEND2BELA" == *OK* ]]; then
    echo "Send to bela"
    echo $PROJECTDIR

#-------------------------------------------------------------------
#From build_project.sh :
#-------------------------------------------------------------------
echo "Start communication with bela"

BELA_EXPERT_MODE=0
BELA_DONT_RUN_FIRST=0

# FUNCTIONS:+++++++++++++++++++++++++++++++
check_rsync(){
    if [ -z "`which rsync 2> /dev/null`" ]
    then
        return 1
    else
        return 0
    fi
}

check_board_alive_and_set_date(){
    printf "Checking the board is up and running at $BBB_ADDRESS..."
    # Clear the host if it is cached in ~/.ssh/known_hosts.
    ssh-keygen -R $BBB_HOSTNAME &> /dev/null || true
    ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 $BBB_ADDRESS "date -s \"`date '+%Y%m%d %T %z'`\" > /dev/null" && printf "done\n" || {
        printf "\nERROR: the board does not respond at $BBB_ADDRESS, check that the address is correct and the board is connected.\n";
        exit 1;
    }
}

#+++++++++++++++++++++++++++++++++++++++++++

# Test if project folder contain correct file(s):
FIND_STRING="find $PROJECTDIR -maxdepth 1 -type f "
EXTENSIONS_TO_FIND='\.cpp\|\.c\|\.S\|\.pd\|\.scd'
FOUND_FILES=$($FIND_STRING 2>/dev/null | grep "$EXTENSIONS_TO_FIND")
if [ -z "$FOUND_FILES" ]
then
    printf "ERROR: Please provide a directory containing .c, .cpp, .S, .pd or .scd files.\n\n"
    exit 1
fi

[ -z $BBB_PROJECT_NAME ] && BBB_PROJECT_NAME="$(basename $(cd "$PROJECTDIR" && pwd))"

echo $PROJECTDIR
echo $BBB_PROJECT_NAME

BBB_PROJECT_FOLDER=$BBB_PROJECT_HOME"/"$BBB_PROJECT_NAME #make sure there is no trailing slash here
BBB_NETWORK_TARGET_FOLDER=$BBB_ADDRESS:$BBB_PROJECT_FOLDER

# The expert will have to remember to run set_date after powering up the board if needed
[ "$BELA_EXPERT_MODE" -eq 0 ] && check_board_alive_and_set_date

# Stop running process
echo "Stop running process..."
ssh $BBB_ADDRESS make QUIET=true --no-print-directory -C $BBB_BELA_HOME stop

# Check if rsync is available
check_rsync && RSYNC_AVAILABLE=1 || RSYNC_AVAILABLE=0

uploadBuildRun(){
    # Copy new source files to the board
    echo "uploadBuildRun START"
    printf "Copying new source files to BeagleBone..."
    if [ "$RSYNC_AVAILABLE" -eq 0 ];
    then
        echo "Using scp..."

        echo "Cleaning the destination folder..."
        #if rsync is not available, brutally clean the destination folder
        ssh $BBB_ADDRESS "rm -rf \"$BBB_PROJECT_FOLDER\"; mkdir -p \"$BBB_PROJECT_FOLDER\""
        echo "Copying the project files"
        scp -r $PROJECTDIR/* "$BBB_NETWORK_TARGET_FOLDER"
    else
        #rsync
        # --delete makes sure it removes files that are not in the origin folder
        # -c evaluates changes using md5 checksum instead of file date, so we don't care about time skews
        # --no-t makes sure file timestamps are not preserved, so that the Makefile will not think that targets are up to date when replacing files on the BBB
        #  with older files from the host. This will solve 99% of the issues with Makefile thinking a target is up to date when it is not.
        echo "Using rsync..."

        rsync -ac --out-format="   %n" --no-t --delete-after --exclude=$BBB_PROJECT_NAME --exclude=build --exclude=settings.json $PROJECTDIR"/" "$BBB_NETWORK_TARGET_FOLDER/" #trailing slashes used here make sure rsync does not create another folder inside the target folder
    fi

    if [ $? -ne 0 ]
    then
        printf "\nError while copying files\n"
        exit
    fi

    # Make new Bela executable and run
    MAKE_COMMAND="make --no-print-directory QUIET=true -C $BBB_BELA_HOME PROJECT='$BBB_PROJECT_NAME' CL='$COMMAND_ARGS' LDLIBS='$BELA_LDLIBS' CPPFLAGS='$BELA_CPPFLAGS' AT="

    ssh -t $BBB_ADDRESS "$MAKE_COMMAND run"
}

echo "Run bela now"
uploadBuildRun

fi
echo "$PROJECTDIR/render.cpp;"
