#!/bin/sh

# Copyright (c) 2016-2017, CZ.NIC, z.s.p.o. (http://www.nic.cz/)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#    * Neither the name of the CZ.NIC nor the
#      names of its contributors may be used to endorse or promote products
#      derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL CZ.NIC BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Automatic updater configuration file
UPDATER_CONFIG='/etc/updater/conf.d/opkg-auto.lua'
# Path to opkg
OPKG='/bin/opkg-cl'

ARGS=""
EXC=0

OPERATION="n"
while [ "$#" -gt 0 ]; do
	case "$1" in
		install)
			OPERATION="i"
			break
			;;
		remove)
			OPERATION="r"
			break
			;;
		upgrade)
			echo "You should not be using opkg upgrade as it is known to break stuff. You have been warned." >&2
			echo "You should be using pkgupdate instead!" >&2
			echo "If you know what you are doing then type YES and continue.." >&2
			read -r iknow
			[ "$iknow" = "YES" ] || exit
			ARGS="$ARGS upgrade"
			break
			;;
		*)
			ARGS="$ARGS $1"
			;;
	esac
	shift
done
shift

if [ "$OPERATION" = "n" ]; then
	# Not install or remove operation
	"$OPKG" $ARGS "$@"
	exit $?
fi


PACKAGES=""
while [ "$#" -gt 0 ]; do
	# ignore options
	if echo "$1" | grep -q '^-'; then
		ARGS="$ARGS $1"
	else
		PACKAGES="$PACKAGES
$1"
	fi

	shift
done

# delete first empty line
PACKAGES="$( echo "$PACKAGES" | sed '1d' )"


# As first takes name of package to be added to config file.
config_add_pkg() {
	echo "Install(\"$1\")" >>"$UPDATER_CONFIG"
}

# Takes single argument, name of package to be removed from config.
config_clean_pkg() {
	sed -e "/^Install\((\| \)\"$1\"/d" -i "$UPDATER_CONFIG"
}

# Checks if package is specified in auto.lua config
config_pkg_in() {
	grep -qe "^Install\((\| \)\"$1\"" "$UPDATER_CONFIG"
}

# Checks if given package is installed
pkg_installed() {
	[ -n "$("$OPKG" $ARGS list-installed "$1")" ]
}

install() {
	local PKG="$1"
	local OPKG_PKG="$PKG"
	if echo "$PKG" | grep -q -E '.*(\.ipk|\.deb)$'; then
		# Source package name from package it self
		local PKGCONTENT=$PKG
		local TMPDIR1=`mktemp -d /tmp/updater-XXXXXX`
		tar -xzf "$PKGCONTENT" -C "$TMPDIR1"
		local TMPDIR2=`mktemp -d /tmp/updater-XXXXXX`
		tar -xzf "$TMPDIR1/control.tar.gz" -C "$TMPDIR2"
		PKG=`sed -ne 's/^Package:[ ]*\([^ ]*\).*/\1/p' "$TMPDIR2/control"`
		rm -rf "$TMPDIR1" "$TMPDIR2"
	fi
	pkg_installed "$PKG"
	local WASINSTALLED=$?
	if ! "$OPKG" $ARGS install "$OPKG_PKG"; then
		# opkg failed, probably some problem with package. Lets not change anything
		EXC=255
		return
	fi
	if [ -n "$PKGCONTENT" ]; then # We have local file (*.ipk or *.deb)
		# Add package file to local repository
		localrepo add --repo auto "$PKGCONTENT"
	fi
	# Add package to config file but only if we really installed it
	if pkg_installed "$PKG" && [ $WASINSTALLED -ne 0 ]; then
		config_clean_pkg "$PKG"
		config_add_pkg "$PKG"
	fi
}

remove() {
	pkg_installed "$1"
	local WASINSTALLED=$?
	if ! "$OPKG" $ARGS remove "$1"; then
		# opkg failed. But continue anyway
		EXC=255
	fi
	if ! pkg_installed "$1"; then
		if ! config_pkg_in "$1" && [ $WASINSTALLED -eq 0 ]; then
			# We show this message only if package was really removed
			echo "WARNING: You probably just removed a package that was installed as part of a user list or the basic system. This package will return durring the next updater run. We suggest you disable the user list instead." >&2
		fi
		config_clean_pkg "$1"
		localrepo clean --repo auto
	fi
}


# Check if $UPDATER_CONFIG exists. Otherwise create.
if [ ! -f "$UPDATER_CONFIG" ]; then
	echo "-- This is automatically generated file managed by opkg wrapper script. Please don't edit!" > "$UPDATER_CONFIG"
fi

echo "$PACKAGES" | while read P; do
	case "$OPERATION" in
		i) # Install
			install "$P"
			;;
		r) # Remove
			remove "$P"
			;;
	esac
done
exit $EXC
