#!/bin/bash
VERSION=${VERSION:-0.13}
## GPLv3
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

if [ -e /etc/sport.conf ]
then source /etc/sport.conf
else
    SBOPATH=${SBOPATH:-/usr/ports}
    MASTER=${MASTER:-"rsync://slackbuilds.org/slackbuilds/14.2/"}
fi

export MAKEOPTS

CWD=$(pwd)
ABS="*"
cleanmode=0

#set -e

## determine arch SUFFIX
if [ -z "$ARCH" ]; then
  case "$( uname -m )" in
  x86_64) SUFFIX="_x86_64" ;;
       *) SUFFIX="" ;;
  esac
fi

## are we cleaning up after we are done?
## this catches a straggler "clean" command after all args
## i figure BSD'ers might do this by force of habit
CLN=$(echo ${@} | rev | cut -f1 -d" ")
if [ "$CLN" = "naelc" -o "$CLN" = "naelc--" -o "$CLN" = "n-" -o "$CLN" = "n" ]; then 
    cleanmode=2
fi

build_pkg() {
    # this function gets and md5checks the source(s)
    # and then executes the .SlackBuild script

    local FILE=${1##*/}
    # what arch do we need?
    # if we are x64 but x64 field is empty..
    if [ X$(cat $FILE.info | grep DOWNLOAD"$SUFFIX"= \
	| cut -f2 -d\") == "X" -a X$SUFFIX == "X_x86_64" ]
    # then pretend we are 32
    then 
	local SUFFIX=""
    fi

    # create an array for downloadable files and md5sums
    ULINK=(`sed -n '/DOWNLOAD'$SUFFIX'/,/MD5SUM'$SUFFIX'/ s_tp.*//_&_1p' $FILE.info | tr -d "\\ "`)
    MD5CHECK=($(sed -n '/MD5SUM'$SUFFIX'/,/DOWNLOAD'$SUFFIX'_/ s_[0-9][a-z]._&_1p' $FILE.info | cut -f2 -d= | tr -d '\\ "' ))

    # echo "DEBUG" ${ULINK[@]}

    # download the sauce
    for item in ${ULINK[@]}; do
	wget --no-clobber $(echo $item | cut -f2 -d'=' | tr -d '"' | tr -d '\\');
    done

    # all sources have been wgotten
    # now check md5sums
    local COUNT=0
    for item in ${MD5CHECK[@]}; do

	local TARBALL=$(basename ${ULINK[$COUNT]} | tr -d '\\ "' )
	local MD5SUM=$(md5sum $TARBALL | cut -f1 -d" ")
	let COUNT++

	if [ $TARBALL ] ; then
	    break
	fi

	if [ "$item" != "$MD5SUM" ]
	then 
	    echo $TARBALL
	    echo "Expected sum " $item
	    echo "What we got: " $MD5SUM
	    echo "O.o md5sums do not match. Continue? [Y/n]"
	    read CONTINUE
	    if [ X$(echo $CONTINUE | tr [:upper:] [:lower:] | cut -b1) != "Xy" ]
	    then exit
	    else
		echo "Boldly continuing with build..."
	    fi
	fi;
    done

    if [ -n "$SWAPPER" ]; then
        if [ -n "$SB_MANDIR" ]; then
	    sed -i  "s%/usr/man%$SB_MANDIR%g"  ./$FILE.SlackBuild
	    echo "user variable override: $SB_MANDIR"
        fi

        if [ -n "$SB_DOCDIR" ]; then
            sed -i  "s%/usr/doc%$SB_DOCDIR%g"  ./$FILE.SlackBuild
	    echo "user variable override: $SB_DOCDIR"
        fi

        if [ -n "$SB_INFODIR" ]; then
            sed -i "s%/usr/info%$SB_INFODIR%g" ./$FILE.SlackBuild
	    echo "user variable override: $SB_INFODIR"
        fi
    fi

    sh ./$FILE.SlackBuild 2> /tmp/sport.log
}

version_return() {
    ## this function pings the website to check current version
    ## and alerts the user if an upgrade is available

    echo "Checking for upgrade..."
    UPGRADE=$(curl --connect-timeout 10 -s slackermedia.info/sport/index.html | grep VERSIONCHECK= | cut -f2 -d"=" )

    if [ "X$VERSION" != "X$UPGRADE" ]; then
	echo "An upgrade of Slackport is available."
    else
	echo "$VERSION is the most up-to-date version available."
    fi

    echo ""
}

untar_pkg() {
    ## this function untars the SlackBuild archive as needed
    ## because SBo SlackBuilds are individually gzipped

    if [ ! -d $SBOPATH/$CATEGORY/$PKG_NAME ] ; then
	tar -xf $SBOPATH/$CATEGORY/$PKG_NAME.tar.gz \
	    -C $SBOPATH/$CATEGORY/ 2> /dev/null || \
	    if [ "X$cleanmode" != "X2" ]; then
	    echo "Errors were found; check the package name, and provide the category."
	    echo $SBOPATH
	    echo CATEGORY
	    echo $PKG_NAME
	    fi
	exit
    fi
}

help() {
    ## this function provides help if the user clearly does
    ## not know how to use the application

    echo "sport [commands] <arguments>"
    echo ""
    echo "sport search foo bar     = search your local Slackbuild tree for foo and bar"
    echo "sport list audio         = list all Slackbuilds in your $TREE/audio dir"
    echo "sport cat foo            = displays the README and .info file for foo"
    echo "sport install foo bar    = build and install foo and bar from your Slackbuild tree"
    echo "sport i \$(<foo.list)     = build and install line-delimited list of packages in foo.list"
    echo "sport i --build-only foo = build but do not install foo"
    echo "sport check foo bar      = fuzzy searches /var/log/packages for foo and bar"
    echo "sport clean foo          = remove source code from $TREE/foo"
    echo "sport rsync              = synchronize your $TREE with your upstream master branch"
    echo "See man page for more information"
    echo ""
}

cat_finder() {
    ## this function determines the path to whatever ARG
    ## the user has provided

    # did we get an absolute path?
    SLASH=$(echo $item | grep "/")

    if [ -z "$SLASH" ]; then
	# no we need to find the absolute path.
	#echo "Auto-detecting category..."
	CATEGORY=$(find "${SBOPATH}" -maxdepth 2 -name "${item}" | rev | cut -f2 -d"/" | rev)
	if [ -z $CATEGORY ]; then
	    echo "File not found."
	    exit
	fi
    else
	# yes we got an absolute path. parse it.
	#echo "Resolving category..."
	CATEGORY=$(echo $item | cut -f1 -d"/")
	item=$(echo $item | cut -f2 -d"/")
	CATEGORY=$(realpath "${SBOPATH}"/$CATEGORY/"${item}".tar.gz | rev | cut -f2 -d"/" | rev)
	if [ -z $CATEGORY ]; then
	    echo "File not found."
	    exit
	fi
    fi

}

local_finder() {
    ## this function determines if the user is actually
    ## wanting to work from the CWD

    if [ "X$item" == "X." ]; then
	item=$(/bin/ls *.SlackBuild | cut -f1 -d'.')
	SBOPATH=.
	CATEGORY=.
	PKG_NAME=$(basename "${item}" .tar.gz)
    else
	# we are not wanting to work from CWD
	return 1
    fi
}

### user interactions below
while [ True ]; do
if [ "$1" = "search" -o "$1" = "--search" -o "$1" = "-s" -o "$1" = "s" ]; then 
    MODE=searchmode
    shift 1
elif [ "$1" = "check" -o "$1" = "--check" -o "$1" = "-k" -o "$1" = "k" ]; then 
    MODE=checkmode
    shift 1
elif [ "$1" = "list" -o "$1" = "--list" -o "$1" = "-l" -o "$1" = "l" -o "$1" = "ls" ]; then 
    MODE=listmode
    shift 1
elif [ "$1" = "cat" -o "$1" = "--cat" -o "$1" = "-c" -o "$1" = "c" ]; then 
    MODE=catmode
    shift 1
elif [ "$1" = "queue" -o "$1" = "--queue" -o "$1" = "-q" -o "$1" = "q" ]; then 
    MODE=installmode
    INSTALLER=${INSTALLER:-echo}
    shift 1
elif [ "$1" = "install" -o "$1" = "--install" -o "$1" = "-i" -o "$1" = "i" ]; then 
    MODE=installmode
    INSTALLER=${INSTALLER:-installpkg}
    shift 1
elif [ "$1" = "rsync" -o "$1" = "--rsync" -o "$1" = "-r" -o "$1" = "r" ]; then 
    rsyncmode=1
    test -d $SBOPATH || mkdir -p $SBOPATH
    rsync -av $MASTER $SBOPATH
    shift 1
elif [ "$1" = "build-only" -o "$1" = "build" -o "$1" = "--build-only" -o "$1" = "-b" -o "$1" = "b" ]; then
    buildmode=1
    INSTALLER=${INSTALLER:-echo}
    shift 1
elif [ "$1" = "clean" -o "$1" = "--clean" -o "$1" = "-n" -o "$1" = "n" ]; then 
    cleanmode=1
    shift 1
elif [ "$1" = "help" -o "$1" = "--help" -o "$1" = "-h" -o "$1" = "h" ]; then 
    true
    shift 1
elif [ "$1" = "version" -o "$1" = "--version" ]; then     
    echo "Slackport version $VERSION"
    version_return
    shift 1
elif [ "$1" = "verbose" -o "$1" = "--verbose" -o "$1" = "-v" -o "$1" = "v" ]; then     
    echo "Slackport version $VERSION"
    version_return
    verbose=1
    shift 1
elif [ "$1" = "swap" -o "$1" = "--swap" ]; then     
    SWAPPER=1
    shift 1
else
    break
fi
done

# everything else left at this point
# SHOULD be a package name, so..
# build an array of packages
ARG=(${@})
ARRAYSIZE=${#ARG[*]}

###### Main Loop
n=0

if [ X"$MODE" != "Xlistmode" ]; then
    if [ "X$ARRAYSIZE" == "X0" ]; then
        help
        exit
    fi
else
    if [ "X$ARRAYSIZE" == "X0" ]; then
        ARG="${SBOPATH}"
    fi
fi

while [ True ]; do
    for item in ${ARG[@]}; do

	CATEGORY=$(echo "$item" | cut -f1 -d"/")
	PKG_NAME=$(basename "$item".tar.gz | cut -f2 -d"/")

	unset ARG[${n}]
	let n++

	if [ "X$MODE" == "Xsearchmode" ]; then
	    cd $SBOPATH
            QUERY=$(echo "$item" | rev | cut -f1 -d"/" | rev)
	    # this separates searches when multiple searches are performed
	    # you can remove it if it bugs you
	    if [ "$verbose" == 1 ]; then
		echo "---------------$QUERY---------------------------"
	    fi
	    for RESULT in $(find $SBOPATH -iname "*${QUERY}*.tar.*" | grep -v asc$ | rev | cut -f1,2 -d"/" | rev); do
		echo -e "$RESULT%"$(tar -xf $SBOPATH/$RESULT -O 2>/dev/null | \
		    grep handy-ruler -A1 | cut -f2 -d":" | tail -n1) ; done | column -s% -t
	    cd $CWD
	fi

	if [ "X$MODE" == "Xcheckmode" ]; then
	    local_finder
	    CHECKER=$(echo "$item" | rev | cut -f1 -d"/" | rev)
            find /var/log/packages/ -iname "*${CHECKER}*"
	fi
    
	if [ "X$MODE" == "Xlistmode" ]; then
	    if [ X"$item" != "X$SBOPATH" ]; then
		QUERY=$(echo "$item" | rev | cut -f1 -d"/" | rev)
		for RESULT in $(ls $SBOPATH/$QUERY | grep tar.gz | grep -v asc$ );
		do echo -e "$RESULT%"$(tar -xf $SBOPATH/$QUERY/$RESULT -O 2>/dev/null | \
		    grep handy-ruler -A1 | cut -f2 -d":" | tail -n1) ; done | column -s% -t
            else
		ls "${SBOPATH}"
                break
            fi
	fi

	if [ "X$MODE" == "Xcatmode" ]; then
	    # are we working from CWD or not?
	    local_finder "${item}"
	    # well, are we?
	    if [ "X$CATEGORY" == "X." ]; then
		cat *{.info,README}
	    else
		# if we are here
		# then we are NOT working from CWD
		# ergo, user thinks this is yum
		cat_finder "$item"
#		echo "category" "$CATEGORY"
		if [ "$verbose" == 1 ]; then
		    echo "------------------------------------------"
		fi
		cat "${SBOPATH}/${CATEGORY}/$(basename ${PKG_NAME} .tar.gz)/"*{.info,README}
	    fi

	    if [ "$verbose" == 1 ]; then
		echo "------------------------------------------"
		echo " " 
	    fi

	fi

	if [ "X$MODE" == "Xinstallmode" ]; then
	    local_finder || cat_finder
	    START=$(find . -iname "${item}.SlackBuild" -maxdepth 0)
	    if [ "X$START" == "X" ]; then
		cd $SBOPATH/$CATEGORY/$(basename $PKG_NAME .tar.gz) 2> /dev/null
	    else
		echo "Working in current directory"
	    fi

	    build_pkg $(basename $PKG_NAME .tar.gz)
	    if [ "X$buildmode" != "X1" ]; then
		$INSTALLER $(ls -Art1 /tmp/`basename $PKG_NAME .tar.gz`*t?z | tail -n1)
	    fi
	    cd $CWD
	fi
#XXX
	if [ "$cleanmode" -ge 1 ]; then
	    cat_finder "$item"
	    rm -r $SBOPATH/$CATEGORY/`basename $PKG_NAME .tar.gz`
	    rm /tmp/$PKG_NAME*SBo*t?z 2> /dev/null
	    tar -xf $SBOPATH/$CATEGORY/$PKG_NAME \
		-C $SBOPATH/$CATEGORY/
	fi

    done
exit
done

