#!/usr/bin/env bash

# Altitude, a simple apt wrapper written in shell
# Code borrowed from Google's Android toolchain repo, file named "build-lucid-multilib-toolchain.sh"

cd $(dirname $(readlink -f ${0}))

DEFAULT_DISTRO="debian"
DEFAULT_RELEASE="buster"
DEFAULT_ARCH="amd64"
MIRROR="http://mirrors.kernel.org"
ALTITUDE_CFG=".altitude/altitude.cfg"
ALTITUDE_INSTALLED_LIST=".altitude/altitude_installed.list.d"
DOWNLOAD_DIR="`mktemp -d /tmp/altitude_dl.XXXXXXX`"

trap "rm -rf ${DOWNLOAD_DIR} && exit" EXIT

help()
{
        cat <<help


                Usage:
                `basename ${0}` [--sysroot] [--mirror] [--release] [--arch] [--distro] <--install || --uninstall> --pkg


help
}

init()
{
	mkdir -p ${ALTITUDE_INSTALLED_LIST}
	echo -e "Which default distro:\n[1] - debian\n[2] - ubuntu\n"
	read DISTRO
	if [ -z ${DISTRO} ]; then
		echo -e "No typed!\nDefaults to: ${DEFAULT_DISTRO}"
		echo "export DISTRO=\"${DEFAULT_DISTRO}\"" >${ALTITUDE_CFG}
	else
		echo "export DISTRO=\"${DISTRO}\"" >${ALTITUDE_CFG}
	fi
	echo -e "Which default distro version:\n"
	read RELEASE
	if [ -z ${RELEASE} ]; then
		echo -e "No typed!\nDefaults to: ${DEFAULT_RELEASE}"
		echo "export RELEASE=\"${DEFAULT_RELEASE}\"" >>${ALTITUDE_CFG}
	else
		echo "export RELEASE=\"${RELEASE}\"" >>${ALTITUDE_CFG}
	fi
	echo -e "Which default destination folder:\n"
	read SYSROOT
	if [ -z ${SYSROOT} ]; then
		echo -e "No typed!\nDefaults to: ${HOME}/altitude"
		echo "export SYSROOT=\"${HOME}/altitude\"" >>${ALTITUDE_CFG}
	else
		echo "export SYSROOT=\"${SYSROOT}\"" >>${ALTITUDE_CFG}
	fi
	echo -e "Which default arch:\n"
	read ARCH
	if [ -z ${ARCH} ]; then
		echo -e "No typed!\nDefaults to: ${DEFAULT_ARCH}"
		echo "export ARCH=\"${DEFAULT_ARCH}\"" >>${ALTITUDE_CFG}
	else
		echo "export ARCH=\"${ARCH}\"" >>${ALTITUDE_CFG}
	fi
}

if [ ${#} != 0 ]; then
	[ -e ${ALTITUDE_CFG} ] && . ${ALTITUDE_CFG}
	for arg in ${@}; do
		v="${arg#*=}"
		case ${arg} in
			--help|-h) help && exit 0 ;;
			--sysroot=*) export SYSROOT="${v}" ;;
			--mirror=*) export MIRROR="${v}" ;;
			--release=*) export RELEASE="${v}" ;;
			--arch=*) export ARCH="${v}" ;;
			--distro=*) export DISTRO="${v}" ;;
			--install) METHOD="install" ;;
			--uninstall) METHOD="uninstall" ;;
			--pkg=*) export PACKAGES="`echo ${v} | tr , ' '`" ;;
			--init) init ;;
		esac
	done
else
	if [ -e ${ALTITUDE_CFG} ]; then
		help
	else
		init
	fi
	exit 0
fi

mkdir -p ${SYSROOT}

# A variant of 'download_file' used to specify the target directory
# $1: source URL
# $2: target directory
download_file()
{
    local URL="$1"
    local DIR="$2"
    local DST="$DIR/`basename $URL`"
    mkdir -p $DIR
    wget -c --no-check-cert "$URL" -O "$DST" || false
}

no_trailing_slash()
{
    echo ${1##/}
}

# Load the Debian packages file. This is a long text file that will list
# each package for a given release.
# $1: Mirror base URL (e.g. http://mirrors.kernel.org/)
# $2: Release name
get_packages_list ()
{
    local RELEASE=$2
    local BASE="`no_trailing_slash \"$1\"`"
    local SRCFILE DSTFILE
	SRCFILE="$BASE/${DISTRO}/dists/$RELEASE/main/binary-$ARCH/Packages.xz"
	DSTFILE="$DOWNLOAD_DIR/Packages-$ARCH.xz"
	download_file "$SRCFILE" "$DSTFILE" || return 1
	(cd $DOWNLOAD_DIR && xzcat Packages-$ARCH.xz/Packages.xz >Packages-$ARCH)


    # Write a small awk script used to extract filenames for a given package
    cat >$DOWNLOAD_DIR/extract-filename.awk <<EOF
BEGIN {
    # escape special characters in package name
    gsub("\\\\.","\\\\.",PKG)
    gsub("\\\\+","\\\\+",PKG)
    FILE = ""
    PACKAGE = ""
}

\$1 == "Package:" {
    if (\$2 == PKG) {
        PACKAGE = \$2
    } else {
        PACKAGE = ""
    }
}

\$1 == "Filename:" && PACKAGE == PKG {
    FILE = \$2
}

END {
    print FILE
}
EOF
}

# Convert an unversioned package name into a .deb package URL
# $1: Package name without version information (e.g. libc6-dev)
# $2: Mirror base URL
# $3: Arch
get_package_deb_url ()
{
    # The following is an awk command to parse the Packages file and extract
    # the filename of a given package.
    local BASE="`no_trailing_slash \"$1\"`"
    local FILE=`awk -f "$DOWNLOAD_DIR/extract-filename.awk" -v PKG=$1 $DOWNLOAD_DIR/Packages-$3`
    if [ -z "$FILE" ]; then
        echo "Could not find filename for package $1"
        exit 1
    fi
    echo "$2/${DISTRO}/$FILE"
}

fix_symlinks()
{
	(
		if [ -d ${SYSROOT}/lib ]; then
			cd ${SYSROOT}/lib
			for i in *; do
				ln -svf */${i} ${i}
			done
		fi
	)
	(
		if [ -d ${SYSROOT}/lib64 ]; then
			cd ${SYSROOT}/lib64
			for i in *; do
				ln -svf */${i} ${i}
			done
		fi
	)
}

install()
{
	get_packages_list "$MIRROR" "$RELEASE"
	rm -f $DOWNLOAD_DIR/SOURCES && touch $DOWNLOAD_DIR/SOURCES
	for PACKAGE in $PACKAGES; do
		echo "Downloading $PACKAGE"
		PKGURL=`get_package_deb_url $PACKAGE $MIRROR $ARCH`
		echo "URL: $PKGURL"
		download_file $PKGURL $DOWNLOAD_DIR || return 1
	done
	#sha1sum $DOWNLOAD_DIR/*.deb | while read LINE; do
	#	PACKAGE=$(basename $(echo $LINE | awk '{ print $2;}'))
	#	SHA1=$(echo $LINE | awk '{ print $1; }')
	#	printf "%-64s %s\n" $PACKAGE $SHA1 >> $DOWNLOAD_DIR/SOURCES
	#done
	for PACKAGE in $PACKAGES; do
		FAKEROOT="`mktemp -d /tmp/altitude_fakeroot.XXXXXXX`"
		PKGURL=`get_package_deb_url $PACKAGE $MIRROR $ARCH`
		SRC_PKG=$DOWNLOAD_DIR/`basename $PKGURL`
		echo "Extracting $SRC_PKG"
		ar -x $SRC_PKG || return 1
		tar -xf data.tar.* -C ${FAKEROOT} || return 1
		rm -f control.tar.* data.tar.* debian-history debian-binary
		(cd ${FAKEROOT}; find . -type f) >${ALTITUDE_INSTALLED_LIST}/${PACKAGE}.list || return 1
		rsync -r ${FAKEROOT}/* ${SYSROOT} >/dev/null 2>&1 || return 1
		rm -rf ${FAKEROOT}
	done
	
	fix_symlinks
}

uninstall()
{
	for PACKAGE in $PACKAGES; do
		for FILE in `cat ${ALTITUDE_INSTALLED_LIST}/${PACKAGE}.list`; do
			(cd ${SYSROOT}; rm -f ${FILE}) || return 1
		done
		rm -f ${ALTITUDE_INSTALLED_LIST}/${PACKAGE}.list || return 1
	done
}

${METHOD}
trap - EXIT
exit 0
