#! /bin/bash
set -e

quiet_boot="0"
. "$pkgdatadir/grub-mkconfig_lib"

export TEXTDOMAIN=grub
export TEXTDOMAINDIR="${datarootdir}/locale"

CLASS="--class gnu-linux --class gnu --class os"

boot_device_id=$GRUB_DEVICE_UUID

LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}

ATOMIC=atomic

UPGRADER=/usr/sbin/deepin-boot-kit
ATOMIC_UPGRADE=/usr/sbin/deepin-upgrade-manager

SNAPSHOT_DIR_PREFIX=/boot/snapshot
SNAPSHOT_DIR=/snapshot

if [ "x${DEEPIN_UPGRADER_VERSION_LIMIT}" = "x" ]; then
    DEEPIN_UPGRADER_VERSION_LIMIT=10
fi

if [ ! -f ${UPGRADER} ];then
    echo "# ${UPGRADER} not found"
    exit 0
fi

lines=`${UPGRADER} --action=list || /bin/true`
while read line
do
    echo "# will parse: ${line}"
    case "$line" in
        "AvailVersionList"*)
            availList=$(echo $line | awk -F ':' '{print $2}' | awk '{gsub(/^\s+|\s+$/, "");print}')
            availList=(${availList// / })
            ;;
    esac
done <<EOT
$lines
EOT

if [ "x${activeVersion}" = "x" ]; then
    echo "# empty active version"
    exit 0
fi

echo "# active: ${activeVersion}"
echo "# avail: ${availList[@]}"

offset=0
limit=$((${offset}+${DEEPIN_UPGRADER_VERSION_LIMIT}))

rollbackList=()
for ver in "${availList[@]}"
do
    if [ $offset -ge $limit ];then
        break
    fi
    type=""
    if [ ! -d "${SNAPSHOT_DIR_PREFIX}/${ver}" ]; then
        type=`${UPGRADER} --action=type --version=${ver}`
        if [ "$?" != "0" ]; then
            continue
        fi
        if [ "${ATOMIC}" = "${type}" ]; then
            ${ATOMIC_UPGRADE} --action=snapshot --version=${ver}
            if [ "$?" != "0" ]; then
                continue
            fi
        fi

    fi

    rollbackList[${offset}]="${ver}"
    offset=$((1+${offset}))
done

if [ x"${#rollbackList[@]}" = x"0" ]; then
    echo "# no version to rollback"
    exit 0
fi
echo "# rollback list: ${rollbackList[@]}"

linux_entry ()
{
    title="$1"
    linux="$2"
    initrd="$3"
    args="$4"

    if [ -z "$boot_device_id" ]; then
        boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
    fi
    echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
    if [ "$quick_boot" = 1 ]; then
        echo "	recordfail" | sed "s/^/$submenu_indentation/"
    fi

  sed "s/^/$submenu_indentation/" << "EOF"
	set	boot=(${root})/boot/
EOF
    # Use ELILO's generic "efifb" when it's known to be available.
    # FIXME: We need an interface to select vesafb in case efifb can't be used.
    arch=`uname -m`
    if [ x"$arch" = x"mips64" ]; then
        need_boot=1
    fi
    if [ x$dirname = x/ ]; then
        if [ -z "${prepare_root_cache}" ]; then
            prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
        fi
        printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/"
    else
        if [ -z "${prepare_boot_cache}" ]; then
            prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)"
        fi
        printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
    fi
    if [ x"$quiet_boot" = x0 ]; then
        message="$(gettext_printf "Loading Linux %s ..." ${version})"
        sed "s/^/$submenu_indentation/" << EOF
	echo	'$(echo "$message" | grub_quote)'
EOF
    fi
    if test -n "${initrd}" ; then
        # TRANSLATORS: ramdisk isn't identifier. Should be translated.
        if [ x"$quiet_boot" = x0 ]; then
            message="$(gettext_printf "Loading initial ramdisk ...")"
            sed "s/^/$submenu_indentation/" << EOF
	echo	'$(echo "$message" | grub_quote)'
EOF
        fi
        sed "s/^/$submenu_indentation/" << EOF
	linux.boot	\${boot}${initrd}
EOF
    fi
  if test -f /boot/bootloader.bin ; then
      message="$(gettext_printf "Loading Linux %s ..." "bootloader.bin")"
      sed "s/^/$submenu_indentation/" << EOF
	echo	'$(echo "$message" | grub_quote)'
EOF
    sed "s/^/$submenu_indentation/" << EOF
	linux.console	\${boot}/bootloader.bin
EOF
    if [ x"$dtbo" = x1 ]; then
        if [ x"$quiet_boot" = x0 ]; then
            message="$(gettext_printf "Loading device tree image ...")"
            sed "s/^/$submenu_indentation/" << EOF
	echo	'$(echo "$message" | grub_quote)'
EOF
        fi
        sed "s/^/$submenu_indentation/" << EOF
	devicetree ${dtbo_rel_dirname}/dtbo.img
EOF
    fi

    if [ x"$need_boot" = x1 ]; then
        echo "	boot" |sed "s/^/$submenu_indentation/"
    fi
    sed "s/^/$submenu_indentation/" << EOF
EOF
  fi
  sed "s/^/$submenu_indentation/" << EOF
	linux.vmlinux	\${boot}${linux} root=${linux_root_device_thisversion} ro ${args}
EOF
  sed "s/^/$submenu_indentation/" << EOF
 	boot
EOF
  sed "s/^/$submenu_indentation/" << EOF
}
EOF
}

get_vmlinux_initrd()
{
    linux="$1"
    basename=`basename $linux`
    dirname=`dirname $linux`
    dtbo_dirname=`dirname $dirname`
    dtbo_rel_dirname=`make_system_path_relative_to_its_root $dtbo_dirname`

    rel_dirname=`make_system_path_relative_to_its_root $dirname`
    version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
    alt_version=`echo $version | sed -e "s,\.old$,,g"`
    if test -e "$dtbo_dirname/dtbo.img"; then
	    dtbo=1
    fi

    INITRD=
    if test -e "${SNAPSHOT_DIR}/initrd.img-${version}"; then
	    INITRD="${rel_dirname}/initrd.img-${version}"
    elif  test -e "${SNAPSHOT_DIR}/initrd.img-${alt_version}";then
        INITRD="${rel_dirname}/initrd.img-${alt_version}"
    fi
    LINUX=${rel_dirname}/${basename}
}

machine=`uname -m`
case "x$machine" in
    xi?86 | xx86_64)
	list=
	for i in /boot/vmlinuz-* /vmlinuz-* /boot/kernel-* ; do
	    if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
	done ;;
    *)
	list=
	for i in /boot/vmlinuz-* /boot/vmlinux-* /vmlinuz-* /vmlinux-* /boot/kernel-* ; do
                  if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi
	done ;;
esac

get_default_vmlinux_initrd()
{
while [ "x$list" != "x" ] ; do
  linux=`version_find_latest $list`
  case $linux in
    *.efi.signed)
      # We handle these in linux_entry.
      list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
      continue
      ;;
  esac
  basename=`basename $linux`
  dirname=`dirname $linux`
  rel_dirname=`make_system_path_relative_to_its_root $dirname`
  version=`echo $basename | sed -e "s,^[^0-9]*-,,g"`
  alt_version=`echo $version | sed -e "s,\.old$,,g"`
  linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

  initrd_early=
  for i in ${GRUB_EARLY_INITRD_LINUX_STOCK} \
	   ${GRUB_EARLY_INITRD_LINUX_CUSTOM}; do
    if test -e "${dirname}/${i}" ; then
      initrd_early="${initrd_early} ${i}"
    fi
  done

  INITRD=
  for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
	   "initrd-${version}" "initramfs-${version}.img" \
	   "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
	   "initrd-${alt_version}" "initramfs-${alt_version}.img" \
	   "initramfs-genkernel-${version}" \
	   "initramfs-genkernel-${alt_version}" \
	   "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
	   "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
    if test -e "${dirname}/${i}" ; then
      INITRD="${i}"
      break
    fi
  done

  LINUX=
  if test -n "${initrd_early}" || test -n "${INITRD}"; then
    initrd="${initrd_early} ${INITRD}"

    initrd_display=
    for i in ${initrd}; do
      initrd_display="${initrd_display} ${dirname}/${i}"
    done
  fi
  LINUX=`make_system_path_relative_to_its_root $linux`
  INITRD=`make_system_path_relative_to_its_root $initrd_display`
  break
done
}

get_linux_image()
{
    arch="$1"
    snapshot="$2"

    case "x$arch" in
        xi?86 | xx86_64)
	        for i in ${snapshot}/vmlinuz-* ${snapshot}/kernel-* ; do
	            if test -e "$i" ; then
                    LINUX="$i"
                    break
                fi
	        done ;;
        *)
	        for i in ${snapshot}/vmlinuz-* ${snapshot}/vmlinux-*  ${snapshot}/kernel-* ; do
	            if test -e "$i" ; then
                    LINUX="$i"
                    break
                fi
	        done ;;
    esac
}

machine=`uname -m`

# disable locale if arch is mips or arm
case "x$machine" in
    xmips*)
        export LC_ALL=C
        ;;
    xaarch*)
        export LC_ALL=C
        ;;
esac

prepare_boot_cache=
prepare_root_cache=
title_correction_code=
submenu_indentation=""
linux_root_device_thisversion="${LINUX_ROOT_DEVICE}"

echo "submenu 'Deepin Rollback Advance Options' \$menuentry_id_option 'gnulinux-advanced-${boot_device_id}' {"
for rollback in "${rollbackList[@]}"
do
    type=`${UPGRADER} --action=type --version=${rollback}`

    LINUX=
    INITRD=
    if [ ${type} = ${ATOMIC} ] ; then
        SNAPSHOT_DIR="${SNAPSHOT_DIR_PREFIX}/${rollback}"
	LINUX=
        get_linux_image "${machine}" "$SNAPSHOT_DIR"
        if [ "x$LINUX" = "x" ] ; then
            continue
        fi
        get_vmlinux_initrd $LINUX
        echo "# not found linux image in ${snap_shot_dir}"
    else
        get_default_vmlinux_initrd
    fi

    menu_entry=$(printf "$(gettext -d deepin-upgrade-manager 'Rollback to %s')" "${rollback}")
    submenu_indentation="$grub_tab"
    linux_entry "$menu_entry" "${LINUX}" "${INITRD}" "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} back_version=${rollback} back_type=${type}"
done
echo "}"
