#!/bin/bash -e


function help
{
    echo
    echo "Creates a new Orocos component package."
    echo " Usage: $(basename $0) [-f] [--catkin] package_name [component] [plugin] [service] [typekit] [support] [empty] [cmake]"
    echo "        $(basename $0) --upgrade [-f] <package_name | directory>"
    echo
    echo " If no package type after the package name is specified, an all-in-one"
    echo " template is created that can serve as everything. You may provide multiple arguments."
    echo
    echo "component    Creates component .hpp/cpp template and cmake logic."
    echo "plugin       Creates plugin .cpp template and cmake logic."
    echo "service      Creates service .cpp template and cmake logic."
    echo "typekit      Creates typekit cmake logic for calling typegen."
    echo "support      Creates support library .cpp template and cmake logic."
    echo "empty        Creates an empty package with only a manifest."
    echo "cmake        Creates a package with only a manifest and CMakelists.txt."
    echo
    echo "Example:"
    echo " $(basename $0) table_filter component service"
    echo "   Creates a package table_filter containing one component and one service."
    echo
    echo "Other command line arguments:"
    echo
    echo " -f          Overwrite existing files."
    echo " --catkin    Create a catkin package.xml file instead of a manifest.xml and a Makefile."
    echo " --upgrade   Upgrade an existing package or all packages found in a directory tree"
    echo "             for the current toolchain release (EXPERIMENTAL)."
    echo
}

if [ x$1 = x ]; then
    help
    exit 1
fi

function upgrade()
{
    dirs=
    found=
    if [ ! "$force" ]; then
        interactive=-i
    fi

    for arg in $*; do
        if [ -d $arg ]; then
            for manifest in `find $arg -name manifest.xml -or -name package.xml`; do dirs="$dirs$(dirname $manifest) "; done
        else
            dirs="$dirs$(rospack find $arg) "
        fi
    done

    for dir in $dirs; do
        if [ -f $dir/Makefile ]; then
            md5=$(md5sum $dir/Makefile | awk '{print $1}')
            if [ "x$md5" = "xb20a34f974b4b692756256654cafaf37" ]; then
                echo "Replacing default Makefile $dir/Makefile with newer version..."
                cp -bv $interactive $templatedir/Makefile $dir/Makefile
                echo
                found_something=1
            fi
        fi
        if [ -f $dir/manifest.xml ]; then
            tempfile=$(mktemp)
            sed 's/<depend package=\"log4cpp\"/<rosdep name=\"log4cpp\"/;
                 s/<depend package=\"ocl\"/<rosdep name=\"ocl\"/;
                 s/<depend package=\"orogen\"/<rosdep name=\"orogen\"/;
                 s/<depend package=\"rtt\"/<rosdep name=\"rtt\"/;
                 s/<depend package=\"rtt_typelib\"/<rosdep name=\"rtt_typelib\"/;
                 s/<depend package=\"typelib\"/<rosdep name=\"typelib\"/;
                 s/<depend package=\"uitlmm\"/<rosdep name=\"uitlmm\"/;
                 s/<depend package=\"uitlrb\"/<rosdep name=\"uitlrb\"/;
                 ' $dir/manifest.xml >$tempfile
            if ! diff $dir/manifest.xml $tempfile >/dev/null; then
                echo "Replacing orocos-toolchain package dependendencies in $dir/manifest.xml with rosdep rules..."
                diff $dir/manifest.xml $tempfile || true
                cp -bv $interactive $tempfile $dir/manifest.xml
                echo
                found_something=1
            fi
            unlink $tempfile
        fi
    done

    if [ ! "$found_something" ]; then
        echo "No package found that needs an upgrade."
    fi

    return 0
}

cwd="$(pwd)"
abspath=$(dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")")

# Detect orocreate-catkin-pkg
if [ "$(basename $0)" = "orocreate-catkin-pkg" ]; then
	catkin=1
fi

# Parse arguments
force=
for arg in $*; do
    case "$arg" in
	-f)
	    force=-p
	    ;;
	--catkin)
	    catkin=1
	    ;;
	--upgrade)
	    upgrade=1
	    ;;
	-h|--help)
	    help
	    exit 1
	    ;;
    -*)
        echo "Unknown command line option '$arg'"
        echo
        help
        exit 1
        ;;
	*)
	    if [ x$pkgname = x ]; then
		pkgname=$arg
	    else
		ptypes="$ptypes $arg"
	    fi
	    ;;
    esac
done

# Locate the template directory. First look in orocos/ros roots
# Default location:
templatedir="$abspath/../share/ocl/templates"

if [ "x$OROCOS_ROOT" != x ]; then
    templatedir="$OROCOS_ROOT/ocl/scripts/pkg/templates"
else

    if [ "x$ROS_ROOT" != x ]; then
	set +e
	oclpath=$(rospack find ocl)
	set -e
	if [ "x$oclpath" != x ]; then
	    templatedir=$oclpath/templates
	fi
	if [ ! -d "$templatedir" ]; then
	    templatedir=$oclpath/templates
	fi
    fi
fi

# If not found, look in $abspath or installed paths.
if [ ! -d "$templatedir" ]; then
    if [ -d "$abspath/templates" ]; then
	templatedir="$abspath/templates"
    fi
fi

# final check:
if [ ! -d "$templatedir" ]; then
    echo "Could not find templates at $templatedir !"
    exit 1
else
    echo "Using templates at $templatedir..."
fi

# Arguments post-processing:
allcappkgname=$(echo $pkgname | tr [:lower:] [:upper:])
cappkgname=$(echo $allcappkgname | cut -c1)$(echo $pkgname | cut -c2-)

if [ "$upgrade" ]; then
  upgrade $pkgname $ptypes
  exit $?
fi
	
if [ x"$ptypes" = x ]; then
    ptypes=all
fi

mkdir $force $pkgname || { echo "Package already exists. Use -f to force creation (will not erase your package but will overwrite generated files)" ; exit 1; }

# different logic depending on package type:
# default files:
if [ "$catkin" ]; then
	files="$templatedir/package.xml $templatedir/CMakeLists.txt"
else
	files="$templatedir/Makefile $templatedir/manifest.xml $templatedir/CMakeLists.txt"
fi
for arg in $ptypes; do
case "$arg" in
    "all")
	srcfiles="$(find $templatedir/src -maxdepth 1 -type f)"
	incfiles="$(find $templatedir/include -maxdepth 1 -type f)"
	cmake_files="component plugin service support"
	typekit=1
	;;
    "empty")
	if [ "$catkin" ]; then
		files="$templatedir/package.xml"
	else
		files="$templatedir/manifest.xml"
	fi
	;;
    "cmake")
	;;
    "typekit")
	incfiles="$templatedir/include/*-types.hpp"
	typekit=1
	;;
    *)
	srcfiles="$srcfiles $templatedir/src/CMakeLists.txt $templatedir/src/*$arg*"
	cmake_files="$cmake_files $arg"
	;;
esac
done

# create src dir if required
if [ "$srcfiles" ]; then
  mkdir $force $pkgname/src
fi
if [ "$incfiles" ]; then
  mkdir -p $pkgname/include/$pkgname
fi

# process template files (drop .tpl suffix if present):
for i in $files; do
    tgtname=$(echo $(basename "$i") | sed -e "s/pkgname/$pkgname/g;s/Pkgname/$cappkgname/g;s/\.tpl//g;")
    cat "$i" | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;" > $pkgname/$tgtname
done

# Done after main CMakeListst.txt is copied:
if [ "$srcfiles" ]; then
  cat $templatedir/cmake/srcdir.cmake | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;"  >> $pkgname/CMakeLists.txt
fi

# Typegen is at toplevel
if [ "$typekit" ]; then
  cat $templatedir/cmake/typekit.cmake | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;"  >> $pkgname/CMakeLists.txt
fi

# process src files:
for i in $srcfiles; do
    tgtname=$(echo $(basename "$i") | sed -e "s/pkgname/$pkgname/g;s/Pkgname/$cappkgname/g;")
    cat "$i" | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;" > $pkgname/src/$tgtname
done
for i in $incfiles; do
    tgtname=$(echo $(basename "$i") | sed -e "s/pkgname/$pkgname/g;s/Pkgname/$cappkgname/g;")
    cat "$i" | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;" > $pkgname/include/$pkgname/$tgtname
done

# add CMake snippets:
for i in $cmake_files; do
  cat $templatedir/cmake/$i.cmake | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;" >> $pkgname/src/CMakeLists.txt
done

if [ "$cmake_files" ]; then
    cat $templatedir/cmake/tail.cmake | sed -e "s/@PKGNAME@/$allcappkgname/g;s/@pkgname@/$pkgname/g;s/@Pkgname@/$cappkgname/g;"  >> $pkgname/CMakeLists.txt
fi

echo "Package $pkgname created in directory $cwd/$pkgname"
exit 0

