#!/bin/sh
#
# Copyright (C) 2013, 2016, 2017, 2019  Etersoft
# Copyright (C) 2013, 2016, 2017, 2019  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-query

confirm_info()
{
	info "$*"
	if [ -z "$non_interactive" ] ; then
		confirm "Are you sure? [y/N]" || fatal "Exiting"
	fi

}

__replace_text_in_alt_repo()
{
	local i
	for i in /etc/apt/sources.list /etc/apt/sources.list.d/*.list ; do
		[ -s "$i" ] || continue
		regexp_subst "$1" "$i"
	done
}

__wcount()
{
	echo "$*" | wc -w
}

__detect_alt_release_by_repo()
{
	local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \
		| grep -v "^#" \
		| grep "[tp][5-9]/branch/" \
		| sed -e "s|.*\([tp][5-9]\)/branch.*|\1|g" \
		| sort -u )
	if [ "$(__wcount $BRD)" = "1" ] ; then
		echo "$BRD"
		return
	fi

	local BRD=$(cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list \
		| grep -v "^#" \
		| grep "Sisyphus/" \
		| sed -e "s|.*\(Sisyphus\).*|\1|g" \
		| sort -u )
	if [ "$(__wcount $BRD)" = "1" ] ; then
		echo "$BRD"
		return
	fi

	return 1
}

__replace_alt_version_in_repo()
{
	local i
	assure_exists apt-repo
	#echo "Upgrading $DISTRNAME from $1 to $2 ..."
	docmd apt-repo list | sed -e "s|\($1\)|{\1}->{$2}|g" | grep -E --color -- "$1"
	# ask and replace only we will have changes
	if a='' apt-repo list | grep -E -q -- "$1" ; then
		__replace_text_in_alt_repo "/^ *#/! s!$1!$2!g"
	fi
	docmd apt-repo list
}

__alt_repofix()
{
	local TO="$1"
	load_helper epm-repofix
	showcmd epm repofix
	(quiet=1 pkg_filenames='' epm_repofix >/dev/null)
	# replace sign name
	if [ -n "$TO" ] ; then
		__replace_text_in_alt_repo "/^ *#/! s!\[alt\]![$TO]!g"
		__replace_text_in_alt_repo "/^ *#/! s!\[sisyphus\]![$TO]!g"
		__replace_text_in_alt_repo "/^ *#/! s!\[updates\]![$TO]!g"
		__replace_text_in_alt_repo "/^ *#/! s!\[[tpc][6-9]\]![$TO]!g"
	fi
}

__get_conflict_release_pkg()
{
	epm qf --quiet --short /etc/fedora-release | head -n1
}

get_fix_release_pkg()
{
	local TOINSTALL=''

	local FORCE=''
	if [ "$1" == "--force" ] ; then
		FORCE="$1"
		shift
	fi

	local TO="$1"

	if [ "$TO" = "Sisyphus" ] ; then
		TO="sisyphus"
		echo "apt-conf-$TO"
	else
		echo "apt-conf-branch"
	fi

	if [ "$FORCE" == "--force" ] ; then
		# assure we have set needed release
		TOINSTALL="altlinux-release-$TO"
	else
		# just assure we have /etc/altlinux-release and switched from sisyphus
		if [ ! -s /etc/altlinux-release ] || epmqf /etc/altlinux-release | grep -q sisyphus ; then
			TOINSTALL="altlinux-release-$TO"
		fi
	fi

	# workaround against obsoleted altlinux-release-sisyphus package from 2008 year
	[ "$TOINSTALL" = "altlinux-release-sisyphus" ] && TOINSTALL="branding-alt-sisyphus-release"

	# update if installed (just print package name here to include in the install list)
	epm --quiet --short -q etersoft-gpgkeys 2>/dev/null

	if [ -n "$TOINSTALL" ] ; then
		echo "$TOINSTALL"

		# workaround against
		#    file /etc/fedora-release from install of altlinux-release-p8-20160414-alt1 conflicts with file from package branding-simply-linux-release-8.2.0-alt1
		# problem
		if __get_conflict_release_pkg | grep -q -v "^altlinux-release" && [ "$TOINSTALL" != "$(__get_conflict_release_pkg)" ] ; then
			echo $(__get_conflict_release_pkg)-
		fi
	fi
}

__update_to_the_distro()
{
	local TO="$1"
	case "$TO" in
		p7)
			__alt_repofix
			docmd epm update || fatal
			docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check an error and run epm release-upgrade again"
			__alt_repofix $TO
			docmd epm update || fatal
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		p8)
			__alt_repofix
			docmd epm update || fatal
			docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check an error and run epm release-upgrade again"
			__alt_repofix $TO
			docmd epm update || fatal
			# sure we have systemd if systemd is running
			if is_installed systemd && is_active_systemd systemd ; then
				docmd epm install systemd || fatal
			fi
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		p9)
			#docmd epm update || fatal
			#docmd epm install rpm apt "$(get_fix_release_pkg --force "$TO")" || fatal "Check an error and run epm release-upgrade again"
			__alt_repofix $TO
			docmd epm update || fatal
			# sure we have systemd if systemd is running
			#if is_installed systemd && is_active_systemd systemd ; then
			#	docmd epm install systemd || fatal
			#fi
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade again"
			;;
		Sisyphus)
			__alt_repofix
			docmd epm update || fatal
			#local ADDPKG
			#ADDPKG=$(epm -q --short make-initrd sssd-ad 2>/dev/null)
			#docmd epm install librpm7 librpm rpm apt $ADDPKG "$(get_fix_release_pkg --force "$TO")" ConsoleKit2- || fatal "Check an error and run again"
			docmd epm upgrade || fatal "Check an error and run epm release-upgrade or just epm upgrade again"
			;;
		*)
	esac
}


__update_alt_to_next_distro()
{
	local TO="$2"
	local FROM="$1"
	[ -n "$TO" ] || TO="$FROM"
	info
 	case "$*" in
		"p6"|"p6 p7"|"t6 p7"|"c6 c7")
			TO="p7"
			confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal
			__replace_alt_version_in_repo "Sisyphus/" "$TO/branch/"
			__replace_alt_version_in_repo "$FROM/branch/" "$TO/branch/"
			__update_to_the_distro "$TO"
			docmd epm update-kernel
			info "Done."
			info "Run epm release-upgrade again for update to p8"
			;;
		"p7"|"p7 p8"|"t7 p8"|"c7 c8"|"p8 p8")
			TO="p8"
			confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal
			__replace_alt_version_in_repo "Sisyphus/" "$TO/branch/"
			__replace_alt_version_in_repo $FROM/branch/ $TO/branch/
			__update_to_the_distro $TO
			docmd epm update-kernel || fatal
			info "Done."
			;;
		"p8"|"p8 p9"|"t8 p9"|"c8 c9"|"p9 p9")
			TO="p9"
			confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal
			__replace_alt_version_in_repo "Sisyphus/" "$TO/branch/"
			__replace_alt_version_in_repo $FROM/branch/ $TO/branch/
			__update_to_the_distro $TO
			docmd epm update-kernel || fatal
			info "Done."
			;;
		"Sisyphus p8")
			TO="p8"
			confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install "$(get_fix_release_pkg "$FROM")" || fatal
			__replace_alt_version_in_repo "$FROM/" "$TO/branch/"
			#__replace_text_in_alt_repo "/^ *#/! s!\[alt\]![$TO]!g"
			__update_to_the_distro $TO
			docmd epm downgrade || fatal
			info "Done."
			;;
		"Sisyphus p9")
			TO="p9"
			confirm_info "Downgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install "$(get_fix_release_pkg "$FROM")" || fatal
			__replace_alt_version_in_repo "$FROM/" "$TO/branch/"
			#__replace_text_in_alt_repo "/^ *#/! s!\[alt\]![$TO]!g"
			__update_to_the_distro $TO
			docmd epm downgrade || fatal
			info "Done."
			;;
		"p8 Sisyphus"|"p9 Sisyphus"|"Sisyphus Sisyphus")
			TO="Sisyphus"
			confirm_info "Upgrade $DISTRNAME from $FROM to $TO ..."
			docmd epm install rpm apt "$(get_fix_release_pkg "$FROM")" || fatal
			docmd epm upgrade || fatal
			__replace_alt_version_in_repo "$FROM/branch/" "$TO/"
			__alt_repofix "sisyphus"
			__update_to_the_distro $TO
			docmd epm update-kernel || fatal
			info "Done."
			;;
		*)
			if [ "$FROM" = "$TO" ] ; then
				info "It seems your system is already updated to newest $DISTRNAME $TO"
			else
				warning "Have no idea how to update from $DISTRNAME $FROM to $DISTRNAME $TO."
			fi
			info "Try run f.i. # epm release-upgrade p8 or # epm release-upgrade Sisyphus"
			info "Also possible you need install altlinux-release-p? package for correct distro version detecting"
			return 1
	esac
}

epm_release_upgrade()
{
	assure_root
	info "Starting upgrade whole system to the next release"
	info "Check also http://wiki.etersoft.ru/Admin/UpdateLinux"

	# TODO: it is possible eatmydata does not do his work
	export EPMNOEATMYDATA=1

	case $DISTRNAME in
	ALTLinux)
		docmd epm update || fatal

		# try to detect current release by repo
		if [ "$DISTRVERSION" = "Sisyphus" ] || [ -z "$DISTRVERSION" ] ; then
			local dv
			dv="$(__detect_alt_release_by_repo)"
			if [ -n "$dv" ] && [ "$dv" != "$DISTRVERSION" ] ; then
				DISTRVERSION="$dv"
				info "Detected running $DISTRNAME $DISTRVERSION (according to using repos)"
			fi
		fi

		# check forced target
		if [ -n "$pkg_filenames" ] ; then
			[ "$(__wcount $pkg_filenames)" = "1" ] || fatal "Too many args: $pkg_filenames"
		fi

		TARGET="$pkg_filenames"

		__alt_repofix


		# TODO: ask before upgrade
		__update_alt_to_next_distro $DISTRVERSION $TARGET
		return
		;;
	*)
		;;
	esac

	case $PMTYPE in
	apt-rpm)
		#docmd epm update
		info "Have no idea how to upgrade $DISTRNAME"
		;;
	*-dpkg)
		assure_exists do-release-upgrade update-manager-core
		sudocmd do-release-upgrade
		;;
	packagekit-*)
		docmd pkcon upgrade-system $pkg_filenames
		;;
	yum-rpm)
		docmd epm install rpm yum
		sudocmd yum clean all
		# TODO
		showcmd rpm -Uvh http://mirror.yandex.ru/fedora/linux/releases/16/Fedora/x86_64/os/Packages/fedora-release-16-1.noarch.rpm
		docmd epm Upgrade
		;;
	dnf-rpm)
		info "Check https://fedoraproject.org/wiki/DNF_system_upgrade for an additional info"
		docmd epm install dnf
		sudocmd dnf --refresh upgrade
		sudocmd dnf clean all
		assure_exists dnf-plugin-system-upgrade
		sudocmd dnf upgrade --refresh
		local RELEASEVER="$pkg_filenames"
		[ -n "$RELEASEVER" ] || RELEASEVER=$(($DISTRVERSION + 1))
		#[ -n "$RELEASEVER" ] || fatal "Run me with new version"
		confirm_info "Upgrade to $DISTRNAME/$RELEASEVER"
		sudocmd dnf system-upgrade download --refresh --releasever=$RELEASEVER
		# TODO: from docs:
		# dnf system-upgrade reboot
		# FIXME: download all packages again
		sudocmd dnf distro-sync --releasever=$RELEASEVER
		info "Run epm autoorphans to remove orphaned packages"
		;;
	urpm-rpm)
		sudocmd urpmi.removemedia -av
		# TODO
		showcmd urpmi.addmedia --distrib http://mirror.yandex.ru/mandriva/devel/2010.2/i586/
		sudocmd urpmi --auto-update --replacefiles
		;;
	zypper-rpm)
		docmd epm repolist
		# TODO
		# sudocmd zypper rr <номер_репозитория>
		showcmd rr N
		showcmd epm ar http://mirror.yandex.ru/opensuse/distribution/11.1/repo/oss 11.1oss
		showcmd zypper ref
		docmd epm update
		docmd epm install rpm zypper
		docmd epm upgrade
		;;
	pacman)
		epm Upgrade
		;;
	conary)
		epm Upgrade
		;;
	emerge)
		epm Upgrade
		;;
	guix)
		sudocmd guix pull --verbose
		;;
	*)
		fatal "Have no suitable command for $PMTYPE"
		;;
	esac

}