#!/bin/bash
# go command

function 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]"
        echo
        return 1
    fi

    NAV=false
    case "$ARG1" in
        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

    SITE=$( ls "$UDEV" | grep -m 1 "$ARG2" )
    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
                    echo "There are $(( j - 1 )) possible paths for ->> $@"
                    j=1
                    for i in ${CHOICES[@]}; 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
                    LOCATION=${CHOICES[$(( num - 1 ))]}
                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() {
    CC=$1
    WDIR=$2
    shift; shift

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

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

    pushd "$WDIR" > /dev/null
    DIR=$(find . -type d -path "$PATT" -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() {
    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
}