function _ros_decode_path {
    local rosname rosdir reldir last rospackdir rosstack_result rosstackdir

    if [[ -z $1 ]]; then
        return 0
    fi

    echo $1 | grep -G '.\+/.*' > /dev/null
		if [[ $? == 0 ]]; then
				rosname=${1%%/*}
        reldir=/${1#*/}
        last=${reldir##*/}        
        reldir=${reldir%/*}/
    else
        rosname=$1
        if [[ -z $2 || $2 != "forceeval" ]]; then
           rosvals=(${rosname})
           return 1
        fi
    fi

    if [[ $rosname == ros ]]; then
        rosdir=${ROS_ROOT}
    elif [[ $rosname == pkg ]]; then
        rosdir=${ROS_PACKAGE_PATH%%:*}
    elif [[ $rosname == log ]]; then
        rosdir=${ROS_ROOT}/log
    elif [[ $rosname == test_results ]]; then
        rosdir=${ROS_ROOT}/test/test_results
    else
        rospackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $rosname 2> /dev/null`
        rospack_result=$?
        rosstackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find $rosname 2> /dev/null`
        rosstack_result=$?
        if [[ $rospack_result == 0 ]]; then
           rosdir=$rospackdir
        elif [[ $rosstack_result == 0 ]]; then
           rosdir=$rosstackdir
        else
            rosvals=(${rosname})
            return 1
        fi
    fi

    rosvals=(${rosname} ${rosdir} ${reldir} ${last})
}

function rospython {
	if [[ -z $1 ]]; then
    if [[ -f ./manifest.xml ]]; then
      pkgname=`basename \`pwd\``
      python -i -c "import roslib; roslib.load_manifest('$pkgname')"
    else
      python
    fi
  else
    python -i -c "import roslib; roslib.load_manifest('$1')"
  fi
}

function roscd {
		local rosvals

    if [ -z $1 ]; then
      cd ${ROS_ROOT}
      return 0
    fi

    _ros_decode_path $1 forceeval
    if [ $? != 0 ]; then
      echo "roscd: No such package '$1'"
      return 1
    elif [ -z ${rosvals[1]} ]; then
      cd ${ROS_ROOT}
      return 0
    else
			cd ${rosvals[2]}${rosvals[3]}${rosvals[4]}
      return 0
    fi
}

function is_integer {
		[ "$1" -eq "$1" ] > /dev/null 2>&1
    return $?
}

function rosd {
		let count=0;
    for items in `dirs`;
    do
        echo $count $items;
        let count=$((count+1));
    done
}

function rospd {
    if is_integer $1; then
        pushd +$1 > /dev/null ;
    else
        local rosvals
        _ros_decode_path $1 forceeval
        pushd ${rosvals[2]}${rosvals[3]}${rosvals[4]} > /dev/null ;
    fi
    rosd
}

function rosls {
    local rosvals
    _ros_decode_path $1 forceeval
    ls ${rosvals[2]}${rosvals[3]}${rosvals[4]} $2
}

function roscmd {
    local pkgdir exepath opt
    pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null`
    if [[ $? != 0 ]] ; then
        echo "Couldn't find package [$1]"
        return 1
    fi
    exepath=(`find $pkgdir -name $2 -type f`)
    if [[ ${#exepath[@]} == 0 ]] ; then
        echo "That file does not exist in that package."
        return 1
    elif [[ ${#exepath[@]} -gt 1 ]] ; then
        echo "You have chosen a non-unique filename, please pick one of the following:"
        select opt in ${exepath[@]}; do
            echo $opt
            break
        done
    else
        opt=${exepath[1]}
    fi
    arg=${opt}
}

function rosed {
    local arg
    roscmd ${1} ${2}
    if [[ -z $EDITOR ]]; then
        vim ${arg}
    else
        $EDITOR ${arg}
    fi
}

function roscp {
    local arg
    roscmd ${1} ${2}
    cp ${arg} ${3}
}

function _roscomplete {
    local arg opts stack_opts
    reply=()
    opts=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names`
    stack_opts=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names`
    IFS=$'\n'
    reply=(${=opts} ${=stack_opts})
		unset IFS
}

function _roscomplete_sub_dir {
    local arg opts rosvals sedcmd stack_opts
    reply=()
    arg="$1"
    _ros_decode_path ${arg}
    if [[ -z ${rosvals[3]} ]]; then
        opts=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names`
        stack_opts=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names`
        IFS=$'\n'
        reply=(${=opts} ${=stack_opts})
        unset IFS
    else
				if [ -e ${rosvals[2]}${rosvals[3]} ]; then
				  sedcmd="s:^${rosvals[2]}:${rosvals[1]}:"g
				  #echo
					#echo $sedcmd
					#echo
          opts=`find ${rosvals[2]}${rosvals[3]} -maxdepth 1 -mindepth 1 -type d ! -regex ".*/[.].*" -print0 | tr '\000' '\n' | sed -e "$sedcmd"`
					#echo $opts
        else
          opts=''
        fi
        IFS=$'\n'
        reply=(${=opts})
        unset IFS
    fi
}

function _roscomplete_search_dir {
    local words arg opts pkgdir
    reply=()
		words=(${=BUFFER})
    pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find ${words[2]} 2> /dev/null`
    pkgdir_result=$?
    stackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find ${words[2]} 2> /dev/null`
    stack_result=$?
    if [[ $pkgdir_result == 0 ]]; then
        opts=`find $pkgdir ${=1} -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g"`
    elif [[ $stack_result == 0 ]] ; then
        opts=`find $stackdir ${=1} -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g"`
    else
        opts=""
    fi
    IFS=$'\n'
    reply=(${=opts})
    unset IFS
}

function _roscomplete_exe {
    _roscomplete_search_dir "-type f -perm +111 -regex .*/.*$"
}

function _roscomplete_file {
    _roscomplete_search_dir "-type f ! -regex .*/[.].* ! -regex .*[.][oa]$"
}

function _roscomplete_launchfile {
    _roscomplete_search_dir "-type f -regex .*\.launch$\|.*\.test$"
}

function _roscomplete_rosbag {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="check compress decompress filter fix help info play record reindex"
        reply=(${=opts})
    else
        reply=()
    fi

}

function _roscomplete_rospack {
    reply=()
    if [[ ${CURRENT} == 2 ]]; then
        opts="help find list list-names langs depends depends-manifests depends1 depends-indent depends-why rosdep rosdep0 vcs vcs0 depends-on depends-on1 export plugins cflags-only-I cflags-only-other libs-only-L libs-only-l libs-only-other profile"
        reply=(${=opts})
    else
        opts=`rospack list-names`
        reply=(${=opts})
    fi
}

function _roscomplete_rosnode {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="ping list info machine kill"
        reply=(${=opts})
    elif [[ ${CURRENT} == 3 ]]; then
        case ${=${(s: :)words}[2]} in
            ping|info|list|kill)
                opts=`rosnode list 2> /dev/null`
                reply=(${=opts})
                ;;
            machine)
                # This takes more logic to determine which machines are present.
                ;;
        esac
    else
        case ${=${(s: :)words}[2]} in
            kill)
                # complete on node name
                opts=`rosnode list 2> /dev/null`
                reply=(${=opts})
                ;;
        esac
    fi

}
function _roscomplete_rosparam {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="set get load dump delete list"
        reply=(${=opts})
    elif [[ ${CURRENT} == 3 ]]; then
        case ${=${(s: :)words}[2]} in
            set|get|delete|list)
                opts=`rosparam list 2> /dev/null`
                reply=(${=opts})
                ;;
            load|dump)
                # complete on files
                reply=(${=opts})
                ;;
        esac
    elif [[ ${CURRENT} == 4 ]]; then
        case ${=${(s: :)words}[2]} in
            load|dump)
                # complete on namespace
                opts=`rosparam list 2> /dev/null`
                reply=(${=opts})
                ;;
        esac
    fi

}
function _roscomplete_rostopic {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="bw echo hz list pub type find info"
        reply=(${=opts})
    elif [[ ${CURRENT} > 2 ]]; then
        case ${=${(s: :)words}[2]} in
            bw|echo|hz|list|type|info)
                if [[ ${=${(s: :)words}[$(( ${CURRENT} -1 ))]} == "-b" ]]; then
                    opts=`find . -maxdepth 1 -type f -not -name ".*" -not -name "*[~#]" | sed 's!.*/!!'`
                    reply=(${=opts})
                else
                    opts=`rostopic list 2> /dev/null`
                    reply=(${=opts})
                fi
                ;;
            find)
                opts=`_msg_opts ${=${(s: :)words[-1]}}`
                reply=(${=opts})
                ;;
            pub)
                if [[ ${CURRENT} == 3 ]]; then
		                opts=`rostopic list 2> /dev/null`
                    reply=(${=opts})
                elif [[ ${CURRENT} == 4 ]]; then
                    opts=`_msg_opts ${=${(s: :)words[-1]}}`
                    reply=(${=opts})
                fi
                ;;
        esac
    fi
}

function _roscomplete_rosservice {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="list call type find uri"
        reply=(${=opts})
    elif [[ ${CURRENT} == 3 ]]; then
        case ${=${(s: :)words}[2]} in
            uri|list|type|call)
                opts=`rosservice list 2> /dev/null`
                IFS=$'\n'
                reply=(${=opts})
                unset IFS
                ;;
            find)
                opts=`_srv_opts ${=${(s: :)words[-1]}}`
                reply=(${=opts})
                ;;
        esac
    fi

}

function _msg_opts {
    unset searchmsg

    if [[ $1 =~ .+/.* ]]; then
        pkgname=${1%%/*}
        msgname=${1#*/}
        searchmsg=1
    else
        pkgname=${1}
    fi

    if [[ -z ${searchmsg} ]]; then
        pkgs=`command rospack list | grep "^${pkgname}"`
        count=0

        opts=""

        for pkg in ${(f)pkgs}; do
            pkgdir=${=${(s: :)pkg}[2]}
            if [[ -d $pkgdir/msg ]]; then
                pkgname2=${=${(s: :)pkg}[1]}
                opts="$opts $pkgname2/"
                count=$((count+1))
            fi
        done

        if [[ $count > 0 ]]; then
            echo $opts
            return 0
        fi
    fi

    pkgpath=`rospack find ${pkgname} 2> /dev/null`
    if [[ $?  == 0 ]] && [[ -d ${pkgpath}/msg ]]; then
        result=`find -L ${pkgpath}/msg -maxdepth 1 -mindepth 1 -name \*.msg ! -regex ".\*/[.].\*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.msg/${pkgname}\/\1/g"`
        echo $result
    fi
}

function _roscomplete_rosmsg {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="show users md5 package packages"
        reply=(${=opts})
    elif [[ ${CURRENT} == 3 ]]; then
        case ${=${(s: :)words}[2]} in
            show|users|md5)
                opts=`_msg_opts ${=${(s: :)words[-1]}}`
                reply=(${=opts})
                ;;
            package)
                opts=`rospack list-names`
                reply=(${=opts})
                ;;
            packages)
                # This shouldn't really have a completion rule
                ;;
        esac
    fi
}

function _srv_opts {
    unset searchsrv

    if [[ $1 =~ .+/.* ]]; then
        pkgname=${1%%/*}
        srvname=${1#*/}
        searchsrv=1
    else
        pkgname=${1}
    fi

    if [[ -z ${searchsrv} ]]; then
        pkgs=`command rospack list | grep "^${pkgname}"`
        count=0

        opts=""

        for pkg in ${(f)pkgs}; do
            pkgdir=${=${(s: :)pkg}[2]}
            if [[ -d $pkgdir/srv ]]; then
                pkgname2=${=${(s: :)pkg}[1]}
                opts="$opts $pkgname2/"
                count=$((count+1))
            fi
        done

        if [[ $count > 0 ]]; then
            echo $opts
            return 0
        fi
    fi

    pkgpath=`rospack find ${pkgname} 2> /dev/null`
    if [[ $?  == 0 ]] && [[ -d ${pkgpath}/srv ]]; then
        result=`find -L ${pkgpath}/srv -maxdepth 1 -mindepth 1 -name \*.srv ! -regex ".\*/[.].\*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.srv/${pkgname}\/\1/g"`
        echo $result
    fi
}

function _roscomplete_rossrv {
    reply=()


    if [[ ${CURRENT} == 2 ]]; then
        opts="show users md5 package packages"
        reply=(${=opts})
    elif [[ ${CURRENT} == 3 ]]; then
        case ${=${(s: :)words}[2]} in
            show|users|md5)
                opts=`_srv_opts ${=${(s: :)words[-1]}}`
                reply=(${=opts})
                ;;
            package)
                opts=`rospack list-names`
                reply=(${=opts})
                ;;
            packages)
                # This shouldn't really have a completion rule
                ;;
        esac
    fi
}



function _roscomplete_roscreate_pkg {
    reply=()


    if [[ ${CURRENT} > 2 ]]; then
        opts=`rospack list-names`
        reply=(${=opts})
    fi
}
compctl -K "_roscomplete_sub_dir" -S / "roscd" "rospd" "rosls"
compctl -K "_roscomplete" "rosmake"

compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_file -- "rosed" "roscp"
compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_exe -- "rosrun"
compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_launchfile -- "roslaunch"
compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_launchfile -- "rostest"
compctl -K "_roscomplete_rospack" "rospack"
compctl -K "_roscomplete_rosbag" "rosbag"
compctl -K "_roscomplete_rosnode" "rosnode"
compctl -K "_roscomplete_rosparam" "rosparam"
compctl -K "_roscomplete_rostopic" "rostopic"
compctl -K "_roscomplete_rosservice" "rosservice"
compctl -K "_roscomplete_rosmsg" "rosmsg"
compctl -K "_roscomplete_rossrv" "rossrv"
compctl -K "_roscomplete_roscreate_pkg" "roscreate-pkg"
