#!/bin/bash
# vim: softtabstop=2 shiftwidth=2 expandtab

# shellcheck disable=SC1091
sources=(
  /lib/profiling-lib.sh
  /etc/zfsbootmenu.conf
  /lib/kmsg-log-lib.sh
  /lib/zfsbootmenu-core.sh
  /lib/zfsbootmenu-ui.sh
)

for src in "${sources[@]}"; do
  # shellcheck disable=SC1090
  if ! source "${src}" >/dev/null 2>&1 ; then
    echo "<3>ZFSBootMenu: unable to source '${src}' in $0" > /dev/kmsg
    exit 1
  fi
done

unset src sources

# prevent ctrl-c from killing us, so that zfs diff can exit cleanly
trap '' SIGINT

snapshot="${1}"
if [ -z "${snapshot}" ]; then
  zerror "snapshot is undefined"
  exit 1
fi

# if a second parameter was passed in and it's a snapshot, compare
# creation dates and make sure diff_target is newer than snapshot
if [ -n "${2}" ] ; then
  sd="$( zfs get -H -p -o value creation "${snapshot}" )"
  td="$( zfs get -H -p -o value creation "${2}" )"
  if [ "${sd}" -lt "${td}" ] ; then
    diff_target="${2}"
  else
    diff_target="${snapshot}"
    snapshot="${2}"
  fi
else
  diff_target="${snapshot%%@*}"
fi

zdebug "snapshot: ${snapshot}"
zdebug "diff target: ${diff_target}"

pool="${snapshot%%/*}"
zdebug "pool: ${pool}"

if ! set_rw_pool "${pool}"; then
  zerror "unable to set ${pool} read/write"
  exit 1 
fi

base_fs="${snapshot%%@*}"
zdebug "base filesystem: ${base_fs}"

CLEAR_SCREEN=1 load_key "${base_fs}"

if ! mnt="$( mount_zfs "${base_fs}" )" ; then
  zerror "unable to mount ${base_fs}"
  exit 1 
fi

zdebug "executing: zfs diff -F -H ${snapshot} ${diff_target}"

# shellcheck disable=SC1064,SC1065
coproc zfs_diff ( zfs diff -F -H "${snapshot}" "${diff_target}" )

# Bash won't use an FD referenced in a variable on the left side of a pipe
exec 3>&"${zfs_diff[0]}"

# shellcheck disable=SC2154
line_one="$( center_string "---${snapshot}" )"
left_pad="${line_one//---${snapshot}/}"
line_one="$( colorize red "${line_one}" )"
line_two="${left_pad}$( colorize green "+++${diff_target}" )"

sed "s,${mnt},," <&3 | HELP_SECTION=diff-viewer ${FUZZYSEL:-fzf} --prompt "> " \
  ${HAS_BORDER:+--border-label="$( global_header )"} \
  --preview="echo -e '${line_one}\n${line_two}'" --no-sort \
  --preview-window="up:${PREVIEW_HEIGHT}${HAS_BORDER:+,border-sharp}" || true

[ -n "${zfs_diff_PID}" ] && kill "${zfs_diff_PID}"
wait "${zfs_diff_PID}" >/dev/null 2>&1

umount "${mnt}"
