#!/bin/bash
# go command

function _begin_sel() {
	local i
	_selected=
	_sel_len=${#_sel_args[@]}
	if [ $_sel_len -gt 1 ]; then
		echo "There are $_sel_len possible paths under $1@[$2]"
		j=1
		for i in ${_sel_args[@]}; do
			echo "    $j. $i"
			j=$(( j + 1 ))
		done

		echo -n "Your choice [1-$(( j - 1 ))]: "
		read num
		re="^[1-$(( j - 1 ))]+\$"
		if [[ ! $num =~ $re ]]; then
			echo "Value does not fall into expected range"
			return 1
		fi
		_selected=${_sel_args[$(( num - 1 ))]}
		return 0
	fi

	_selected=${_sel_args[0]}
	return 0
}

function go() {
	local i _GO
    ARG1=$1; ARG2=$2; ARG3=$3;

    if [[ -z "$ARG1" ]]; then
        __func_head "[MODE] SITE TARGET_DIR [..SLICE]"
        __func_help "up [MODE] TARGET_DIR"
        __func_help "down [MODE] TARGET_DIR [..SLICE]"
		__func_help "compiler commands use \"go help\""
        echo
        return 1
    fi

    NAV=false
    case "$ARG1" in
		bug|build|clean|doc|env|fix|fmt|generate|get|install|list|mod|work|run|test|tool|version|vet|help)
			_GO=$( which go )
			"$_GO" $@
			return $?
			;;
        p)
            shift
            CC='pushd' ;;
        c)
            shift
            CC='cd' ;;
        e)
            shift
            CC='echo' ;;
        up|down)
            shift
            NAV=true ;;
        *)
            CC='cd'
            ARG3=$ARG2
            ARG2=$ARG1
            ;;
    esac

    if [ $NAV = true ]; then
        __go_nav $ARG1 $@
        return $?
    fi

    if [[ -f ~/.go_conf ]]; then
        source ~/.go_conf
    else
        echo "Cannot source config file"
        return 1
    fi

	_sel_args=( $( ls "$UDEV" | grep "$ARG2" ) )
	_begin_sel $UDEV $ARG2

    SITE=$_selected
    if [[ -z "$SITE" ]]; then
        echo "No such site: $ARG2"
        find "$UDEV/" -maxdepth 1 -type d | sed "s/^.\+\/\([^\/]\+\)\/\?$/    \1/g"
        return 1
    fi

    if [[ -z "$ARG3" ]]; then
        $CC "$UDEV/$SITE"
        return $?
    fi

    __SFT23=0
    for ((i = 0; i < ${#LOCS[@]}; i++))
    do
        LOC=${LOCS[i]}
        LOCATION=$(ls -d "$UDEV/$SITE/$LOC/"*"$ARG3"*/ 2> /dev/null )
        if [[ -n "$LOCATION" ]]; then
            NPATHS=$( echo -n "$LOCATION" | grep -c '^' )
            if [[ $NPATHS -gt 1 ]]; then

                # shift ARG2 ARG3
                shift; shift
                __SFT23=1

                j=1
                CHOICES=()
                __CC=$CC
                for i in ${LOCATION[@]}; do
                    __dive "test -d" "$i" $@ > /dev/null
                    if [[ $? -eq 0 ]]; then
                        __LOC="$i"
                        CHOICES+=($i)
                        j=$(( j + 1 ))
                    fi
                done
                CC=$__CC

                # No possible solution for this path
                if [[ $j -eq 1 ]]; then
                    echo "Unable to trace \"$@\" under $UDEV/$SITE/*$ARG3*/"
                    return 1
                elif [[ $j -eq 2 ]]; then
                    LOCATION=$__LOC
                else
					_sel_args=$CHOICES
					_begin_sel "$LOCATION" $@
					if [ -z $_selected ]; then
						return 1
					fi
					LOCATION=$_selected
                fi
            fi
            break
        fi
    done

    if [[ $__SFT23 -eq 0 ]]; then
        # shift ARG2 ARG3
        shift; shift
    fi

    if [[ -n "$LOCATION" ]]; then
        __dive $CC "$LOCATION" $@
        return $?
    else
        __dive $CC "$UDEV/$SITE" "$ARG3" $@
        return $?
    fi
}

__dive() {
	local i
    CC=$1
    WDIR=$2
    shift; shift

    if [ -z "$*" ]; then
        $CC "$WDIR"
        return $?
    fi

	_EXCLUDE_ARGS=
	if [ -n $EXCLUDE_DIRS ]; then
		for i in ${EXCLUDE_DIRS[@]}; do
			_EXCLUDE_ARGS="$_EXCLUDE_ARGS -path '*/$i' -prune -o -name $i -prune -o"
		done
	fi

    OIFS=$IFS
    IFS="*"
    PATT="*$**"
    IFS=$OIFS

    pushd "$WDIR" > /dev/null
	DIR=$(find . $_EXCLUDE_ARGS -path "$PATT" -type d -print -quit | cut -c 3- )
    popd > /dev/null

    if [[ -z $DIR ]]; then
        echo "Path: $WDIR"
        echo "  - Pattern not found: $PATT"
        return 1
    fi

    $CC "$WDIR/$DIR"
}

__go_nav() {
	local i
    ARG1=$1; ARG2=$2; ARG3=$3;
    case "$ARG2" in
        p)
            shift
            CC='pushd' ;;
        c|"")
            shift
            CC='cd' ;;
        e)
            shift
            CC='echo' ;;
        *)
            CC='cd'
            ARG3=$ARG2
            ;;
    esac

    if [[ "$ARG1" == "up" ]]; then
        OIFS=$IFS
        IFS="/" read -a PWDA <<< "$(pwd)"
        IFS=$OIFS

        MARK=0
        S_LEN=$(( ${#PWDA[@]} - 2 ))
        for (( i=1; i<=$S_LEN; i++ ))
        do
            STACK=${PWDA[$i]}
            if [ -z "$STACK" ]; then
                continue
            fi

            if [ -n "$ARG3" ] && [[ "$STACK" =~ "$ARG3" ]]; then
                MARK=$i
            fi
        done

        if [ -z "$ARG3" ]; then
            # Go up 1 level
            MARK=$(( ${#PWDA[@]} - 2 ))
        fi

        if [ $MARK -eq 0 ]; then
            echo "No such token in up stack: $ARG3"
            for (( i=1; i<=$S_LEN; i++ )); do echo "    ${PWDA[$i]}"; done
            return 1
        fi

        DIR='/'

        for (( i=1; i<=$MARK; i++ ))
        do
            DIR="$DIR${PWDA[$i]}/"
        done

        $CC "$DIR"
    else
        shift
        __dive $CC . $@
        return $?
    fi
}