#! /bin/bash -e

#####################################################################
#                                                                   #
#               Compiles Faust programs to ROS packages             #
#               (c) Grame, 2014                                     #
#                                                                   #
#####################################################################

. faustpath
. faustoptflags

CXXFLAGS+=" $MYGCCFLAGS"  # So that additional CXXFLAGS can be used

ARCHFILE=$FAUSTARCH/jack-ros.cpp

path=$(pwd)
CURRENT_DIR=$(pwd)

# Dispatch command arguments
WORKSPACES=''
NEW_NAMES=''

params=("$@")
n=0
for p in $@; do
    n=$(($n+1))
    # install option, get workspace's name
    if [ "$p" = "-install" ]; then
        WORKSPACES="$WORKSPACES ${params[$n]}"
    # o option, get the new application's name
    elif [ "$p" = "-o" ]; then
        NEW_NAMES="$NEW_NAMES ${params[$n]}"
    elif [ "$p" = "--help" ] || [ "$p" = "-h" ] ; then
        HELP=true
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p ${params[$n]}"
    elif [[ -f "$p" ]] && [ ${p: -4} == ".dsp" ]; then
        FILES="$FILES $p"
    fi
done

# Puts option parameters in tables
NEW_NAMES=($NEW_NAMES)
WORKSPACES=($WORKSPACES)

# Get parameters tables size
NAMES_LENGTH=${#NEW_NAMES[@]}
WS_LENGTH=${#WORKSPACES[@]}

if [ $HELP ]
then
############ BEGIN HELP MESSAGE ############
    echo -e "####################################################################################################
######################################## FAUST2ROS HELP ############################################
####################################################################################################

################################################################################################
                This command allows you to compile a FAUST DSP file into a ROS package,
                        compressed or ready to be used in a workspace.
################################################################################################
USAGE:
faust2ros ~/path/to/mydsp.dsp
Output : mydsp.zip, a compressed package

OPTIONS :
        -install
                faust2ros -install ~/path/to/my/workspace ~/other/path/to/mydsp.dsp
                Output : mydsp.cpp, a C++ file in a package, in a workspace,
                                                        ready to be run
        -o
                faust2ros -o mynewname ~/path/to/mydsp.dsp
                Output : mynewname.zip

For more options and information, type faust -h or faust --help

####################################################################################################
"
############ END HELP MESSAGE ############
else

    # Check if packages exist ; if not, create them
    i=0
    for (( i = 0 ; i < $WS_LENGTH ; i=$i+1 ))
    do
        if [ ! -d ${WORKSPACES[${i}]} ]
        then
            mkdir -p ${WORKSPACES[${i}]}/src
        else
            cd ${WORKSPACES[${i}]}
            if [ ! -d src ]
            then
                mkdir src
            fi
        fi
        cd ${WORKSPACES[${i}]}/src
        if [ !  CMakeLists.txt ] || [ -w CMakeLists.txt ]
        then
            rm -f CMakeLists.txt
            catkin_init_workspace > /dev/null
        fi
    done

    # if there is only one workspace specified, no need to run a loop
    if [ $WS_LENGTH = 1 ]; then
         WORKSPACE_PATH="${WORKSPACES[$1]}"/src
    fi

    #-------------------------------------------------------------------
    # compile the *.dsp files
    #
    i=0

    for p in $FILES
    do
        # Check .dsp path ; if there is no path, file should be in current directory
        temp=$(basename "$p")
        temp_path=$(dirname ${p})

        if [ ! $temp_path = '.' ]
        then
            p=$temp
            path=$temp_path
        fi

        # Create dsp package depending on options
        if [ "$NEW_NAMES" = "" ]
        then
            f=$(basename "$p")
            name="${f%.dsp}"
        else
            name="${NEW_NAMES[${i}]}"
        fi
            # zip file
        if [ $WS_LENGTH = 0 ]
        then
            cd $CURRENT_DIR

            temp_dir=$(mktemp -d ROS.XXXXXX)
            cd $temp_dir
            mkdir src
            cd src
            catkin_create_pkg $name roscpp std_msgs > /dev/null

            PACKAGE_PATH=$CURRENT_DIR/$temp_dir/src/$name
        else
            # install in workspace
            if [ $WS_LENGTH = 1 ]
            then
                cd $WORKSPACE_PATH
                if [[ -d $WORKSPACE_PATH/$name ]]
                then
                    rm -r $WORKSPACE_PATH/$name
                fi

                catkin_create_pkg $name roscpp std_msgs > /dev/null

                PACKAGE_PATH=$WORKSPACE_PATH/$name

            else
                WORKSPACE_PATH="${WORKSPACES[${i}]}"/src
                cd $WORKSPACE_PATH
                if [ -d $WORKSPACE_PATH/$name ]
                then
                    rm - r $WORKSPACE_PATH/$name
                fi

                catkin_create_pkg $name roscpp std_msgs > /dev/null

                PACKAGE_PATH=$WORKSPACE_PATH/$name
            fi
        fi
        cd $PACKAGE_PATH

# Set CMakeLists.txt to fit to the faust package
############## CMAKELISTS ############################
        echo -e "cmake_minimum_required(VERSION 2.8.3)
project($name)

SET(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -O3 -mfpmath=sse -msse -msse2 -msse3 -ffast-math\")

include_directories(\${catkin_INCLUDE_DIRS})

catkin_package()
find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

add_executable(\${PROJECT_NAME} src/\${PROJECT_NAME}.cpp)

target_link_libraries(\${PROJECT_NAME} jack \${catkin_LIBRARIES})" > CMakeLists.txt
############# END CMAKELISTS #########################

        # double compilation
        cd src
        faust -i -a ros-callbacks.cpp -o "$PACKAGE_PATH/src/$name.cpp" $path/$p || exit
        $CXX $name.cpp -o $name || exit
        faust -i -a $ARCHFILE $OPTIONS "$path/$p" -o "$PACKAGE_PATH/src/$name.cpp" $path/$p    > /dev/null || exit
        ./$name        # adds the callbacks declaration to the generated c++ file
        rm $name
        # zip file
        if [ $WS_LENGTH = 0 ]
        then
            cd $CURRENT_DIR/$temp_dir/src/$name
############ BEGIN README ###########################
            echo -e "                        README : Using Faust with ROS
                Grame, Centre National de Creation Musicale
                ###########################################

This file was automatically generated with faust2ros or faust2rosgtk

To run your new application :
        1) unzip this package into a ROS workspace.
        2) source this workspace :
                a) go in your workspace's root
                b) type 'source devel/setup.bash'
        3) run with 'rosrun myapp myapp'

For more information, check the documentation :
https://sourceforge.net/p/faudiostream/code/ci/master/tree/documentation" > README.txt
############ END README #############################
            cd $CURRENT_DIR/$temp_dir/src
            zip -r $name.zip $name > /dev/null
            cd $CURRENT_DIR
            cp $temp_dir/src/$name.zip $CURRENT_DIR
            rm -r $temp_dir
            OUTPUT="$OUTPUT $name.zip;"
            # package installation
        else
            cd ${WORKSPACES[${i}]}
############ BEGIN README ###########################
            echo -e "                        README : Using Faust with ROS
                Grame, Centre National de Creation Musicale
                ###########################################

This file was automatically generated with faust2ros or faust2rosgtk

To run your new application :
        1) source this workspace :
                a) go in your workspace's root
                b) type 'source devel/setup.bash'
        3) run with 'rosrun myapp myapp'

For more information, check the documentation :
https://sourceforge.net/p/faudiostream/code/ci/master/tree/documentation" > README.txt
############ END README #############################
            catkin_make > /dev/null || exit
            OUTPUT="$OUTPUT $name.cpp;"
        fi

        i=$((i+1))

    done

    echo $OUTPUT
fi
