#!/bin/sh
#
# Copyright (C) 2012, 2017, 2018, 2021  Etersoft
# Copyright (C) 2012, 2017, 2018, 2021  Vitaly Lipatov <lav@etersoft.ru>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

load_helper epm-check_updated_repo

__epm_print_excluded()
{
	local pkgs="$1"
	local fullpkgs="$2"
	local excluded
	excluded="$(estrlist exclude "$pkgs" "$fullpkgs")"
	if [ -n "$excluded" ] ; then
		echo "Skipped manually installed:"
		estrlist union $excluded
	fi
}

__epm_autoremove_altrpm_pp()
{
	local pkgs fullpkgs

	info "Removing unused python/perl modules..."

	local libexclude="$1"

	local flag=

	showcmd "apt-cache list-nodeps | grep -E -- \"$libexclude\""
	fullpkgs=$(apt-cache list-nodeps | grep -E -- "$libexclude" )
	pkgs=$(skip_manually_installed $fullpkgs)

	if [ -n "$dryrun" ] ; then
		info "Packages for autoremoving:"
		echo "$pkgs"
		__epm_print_excluded "$pkgs" "$fullpkgs"
		return 0
	fi

	if [ -n "$pkgs" ] ; then
		info "The command we will run:"
		showcmd rpm -v -e $pkgs
		__epm_print_excluded "$pkgs" "$fullpkgs"

		confirm_info "We will remove unused (without dependencies) packages above."

		sudocmd rpm -v -e $pkgs && flag=1
	fi


	if [ -n "$flag" ] ; then
		info ""
		info "call again for next cycle until all modules will be removed"
		__epm_autoremove_altrpm_pp "$libexclude"
	fi

	return 0
}

__epm_autoremove_altrpm_package_group()
{
	if epmqp "$*" ; then
		confirm_info "We will remove unused (without dependencies) packages above."
		docmd epm remove $(epmqp --short "$*")
	fi
}

__epm_autoremove_altrpm_lib()
{
	local pkgs fullpkgs

	local flag=''
	local opt="$1"
	local libgrep=''
	info
	case "$opt" in
		libs)
			info "Removing all non -devel/-debuginfo libs packages not need by anything..."
			local develrule='-(devel|devel-static)$'
			libgrep='^(lib|bzlib|zlib)'
			;;
		i586-libs)
			info "Removing all non -devel/-debuginfo i586-libs packages not need by anything..."
			local develrule='-(devel|devel-static)$'
			libgrep='^(i586-lib|i586-bzlib|i586-zlib)'
			;;
		devel)
			info "Removing all non -debuginfo libs packages (-devel too) not need by anything..."
			local develrule='-(NONONO)$'
			libgrep='^(lib|bzlib|zlib)'
			;;
		*)
			fatal "Internal error: unsupported opt $opt"
	esac

	# https://www.altlinux.org/APT_в_ALT_Linux/Советы_по_использованию#apt-cache_list-nodeps
	showcmd "apt-cache list-nodeps | grep -E -- \"$libgrep\""
	fullpkgs=$(apt-cache list-nodeps | grep -E -- "$libgrep" \
		| sed -e "s/[-\.]32bit$//g" \
		| grep -E -v -- "$develrule" \
		| grep -E -v -- "-(debuginfo)$" \
		| grep -E -v -- "-(util|utils|tool|tools|plugin|daemon|help)$" \
		| grep -E -v -- "^(libsystemd|libreoffice|libnss|libvirt-client|libvirt-daemon|libsasl2-plugin|eepm|distro_info)" )
	pkgs=$(skip_manually_installed $fullpkgs)

	if [ -n "$dryrun" ] ; then
		info "Packages for autoremoving:"
		echo "$pkgs"
		__epm_print_excluded "$pkgs" "$fullpkgs"
		return 0
	fi

	if [ -n "$pkgs" ] ; then
		info "The command we will run:"
		showcmd rpm -v -e $pkgs
		__epm_print_excluded "$pkgs" "$fullpkgs"
		confirm_info "We will remove unused (without dependencies) packages above."

		sudocmd rpm -v -e $pkgs && flag=1
	fi

	if [ -n "$flag" ] ; then
		info ""
		info "call again for next cycle until all libs will be removed"
		__epm_autoremove_altrpm_lib $opt
	fi

	return 0
}


epm_autoremove_default_groups="python2 python3 perl gem ruby libs"

__epm_autoremove_altrpm()
{
	local i
	load_helper epm-packages
	assure_exists /usr/share/apt/scripts/list-nodeps.lua apt-scripts

	if [ -z "$pkg_names" ] ; then
		pkg_names="$epm_autoremove_default_groups"
	elif [ "$pkg_names" = "python" ] ; then
		pkg_names="python2 python3"
	fi

	for i in $pkg_names ; do
		case $i in
		libs)
			__epm_autoremove_altrpm_lib libs
			;;
		i586-libs)
			__epm_autoremove_altrpm_lib i586-libs
			;;
		debuginfo)
			__epm_autoremove_altrpm_package_group '-debuginfo-'
			;;
		devel)
			__epm_autoremove_altrpm_package_group '^(rpm-build-|gcc-|glibc-devel-)'
			;;
		python2)
			__epm_autoremove_altrpm_pp '^(python-module-|python-modules-)'
			;;
		python3)
			__epm_autoremove_altrpm_pp '^(python3-module-|python3-modules-)'
			;;
		php)
			__epm_autoremove_altrpm_pp '^(php7-|php5-|php8-)'
			;;
		gem)
			__epm_autoremove_altrpm_pp '^(gem-)'
			;;
		ruby)
			__epm_autoremove_altrpm_pp '^(ruby-)'
			;;
		perl)
			__epm_autoremove_altrpm_pp '^(perl-)'
			;;
		libs-devel)
			__epm_autoremove_altrpm_lib devel
			;;
		*)
			fatal "autoremove: unsupported '$i'. Use epm autoremove --help to list supported ones"
			;;
		esac
	done

	return 0
}

epm_autoremove_print_help()
{
	echo "epm autoremove removes unneeded packages from the system"
	echo "run 'epm autoremove' to use apt-get autoremove"
	echo "or run 'epm autoremove --direct [group1] [group2] ...' to use epm implementation"
	echo "Default groups: $epm_autoremove_default_groups"
	cat <<EOF
Supported package groups:
    libs       - unused libraries
    libs-devel - unused -devel packages
    i586-libs  - unused i586-libs libraries
    debuginfo  - all debuginfo packages
    devel      - all packages used for build/developing
    python     - all python modules
    python2    - python2 modules
    python3    - python3 modules
    perl       - perl modules
    gem        - gem modules
    ruby       - ruby modules

Use
--auto|--assumeyes|--non-interactive  for non interactive mode
EOF
}


# TODO: keep our eepm package
epm_autoremove()
{

case $DISTRNAME in
	ALTLinux|ALTServer)
		if [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "help" ] ; then
			epm_autoremove_print_help
			return 0
		fi

		if [ -z "$direct" ] ; then
			[ -n "$1" ] && fatal "Run autoremove without args or with --direct. Check epm autoremove --help to available commands."
			sudocmd apt-get $(subst_option non_interactive -y) autoremove $dryrun
			local RET=$?
			if [ "$RET" != 0 ] ; then
				echo
				info "Also you can run 'epm autoremove --direct' to use epm implementation of autoremove (see --help)"
				return
			fi
		else
			__epm_autoremove_altrpm "$@"
		fi

		[ -n "$dryrun" ] && return

		# remove old kernels only by a default way
		[ -n "$1" ] && return

		docmd epm remove-old-kernels $(subst_option non_interactive -y)

		if [ -z "$direct" ] ; then
			echo
			info "Also you can run 'epm autoremove --direct' to use epm implementation of autoremove (see --help)"
		fi

		return
		;;
	*)
		;;
esac

[ -z "$pkg_filenames" ] || fatal "No arguments are allowed here"

case $PMTYPE in
	apt-dpkg|aptitude-dpkg)
		sudocmd apt-get autoremove local $(subst_option non_interactive -y) $dryrun
		;;
	aura)
		if [ -n "$dryrun" ] ; then
			fatal "--dry-run is not supported yet"
		fi
		sudocmd aura -Oj
		;;
	packagekit)
		docmd pkcon repair --autoremove
		;;
	yum-rpm)
		# cleanup orphanes?
		while true ; do
			# shellcheck disable=SC2046
			docmd package-cleanup --leaves $(subst_option non_interactive --assumeyes)
			# FIXME: package-cleanup have to use stderr for errors
			local PKGLIST=$(package-cleanup -q --leaves | grep -v "^eepm-")
			[ -n "$PKGLIST" ] || break
			docmd epm remove $PKGLIST
		done
		;;
	dnf-rpm)
		if [ -n "$dryrun" ] ; then
			fatal "--dry-run is not supported yet"
		fi
		sudocmd dnf autoremove
		;;
	# see autoorhans
	#urpm-rpm)
	#	sudocmd urpme --auto-orphans
	#	;;
	emerge)
		if [ -n "$dryrun" ] ; then
			fatal "--dry-run is not supported yet"
		fi
		sudocmd emerge --depclean
		assure_exists revdep-rebuild
		sudocmd revdep-rebuild
		;;
	# see autoorhans
	#pacman)
	#	sudocmd pacman -Qdtq | sudocmd pacman -Rs -
	#	;;
	slackpkg)
		# clean-system removes non official packages
		#sudocmd slackpkg clean-system
		;;
	guix)
		sudocmd guix gc
		;;
	pkgng)
		sudocmd pkg autoremove
		;;
	zypper-rpm)
		# https://www.linux.org.ru/forum/desktop/11931830
		assure_exists zypper zypper 1.9.3
		sudocmd zypper packages --unneeded
		# FIXME: x86_64/i586 are duplicated
		local PKGLIST=$(zypper packages --unneeded | tail -n +5 | cut -d \| -f 3 | sort -u)
		showcmd epm remove --clean-deps $PKGLIST
		;;
	xbps)
		if [ -n "$dryrun" ] ; then
			fatal "--dry-run is not supported yet"
		fi
		sudocmd xbps-remove -O
		;;
	opkg)
		if [ -n "$dryrun" ] ; then
			sudocmd opkg --noaction --autoremove
		else
			sudocmd opkg --autoremove
		fi
		;;
	*)
		fatal "Have no suitable command for $PMTYPE"
		;;
esac

}