#!/bin/bash
#
# vmbremovepkg
#
# Given a target package to remove, include a list of dependent packages.
# Check with user before removing all the listed packages.

# ! Requires: hoorex > 0.10.1
#
if [ "$(printf "0.10.1\n%s\n" "$(hoorex --version)" |sort -V |tail -1)" = "0.10.1" ]; then
  echo "This version of HooRex ($(hoorex --version)) is not usable here."
  echo "Please update to hoorex-0.10.2 or later."
fi
HOOREX=/usr/bin/hoorex

# vmb{install,remove}pkg version
#
VERSION=%VERSION%

# The vmbinstallpkg command requires a single argument;
# either
#    the name of a package
#    or the -f (--force-update) directive
#    or the -v (--version) option
#
TARGETPKG=$1
[ -z "$TARGETPKG" ] && {
  echo "No target package supplied. Exiting now ..."
  exit 1
}

SL_RELEASE=${SL_RELEASE:-$(cut -d' ' -f 2 < /etc/slackware-version)}
SL_ARCH=${SL_ARCH:-$(uname -m)}
#echo "$SL_RELEASE $SL_ARCH"

# vmbremovepkg's home is with vmbinstallpkg
#
VMBINST_HOME="$HOME/.local/share/vmbinstallpkg"

# Temporary directory to do work
#
VMB_TEMPDIR=$(mktemp -d -t .vmb_tmp_dir-XXXXXX)
#echo "Created $VMB_TEMPDIR"

# Retrieve default settings
# vmb{install,remove}pkg share the same defaults file
#
if [ -r /etc/default/vmbinstallpkg ]; then
  . /etc/default/vmbinstallpkg
fi

# REPODATA_DIR is where we keep any downloaded repoData.{pkl,stamp}
# for use by vmbremovepkg
#
REPODATA_DIR="$VMBINST_HOME/$SL_RELEASE"
TEMP_REPODATA_DIR="$REPODATA_DIR/tmp"
mkdir -p "$TEMP_REPODATA_DIR"

# REPODATA_DIR is location of a downloaded repoData.{pkl,stamp},
# and REPODATA_AGE_CHECK is the interval after which we check that
# our downloaded version is up to date.
#REPODATA_AGE_CHECK="5 min ago"
REPODATA_AGE_CHECK=${REPODATA_AGE_CHECK:-"3 days ago"}
#echo "REPODATA_AGE_CHECK = $REPODATA_AGE_CHECK"

# HOOREX_DB is the directory location of the source of the hoorex database
# (repoData.pkl) we'll be copying for us to use in REPODATA_DIR.
# The default HOOREX_DB location is in directory ~/.local/share/hoorex
# but for special needs the location may be set using -p option for hoorex e.g.
#     hoorex -f -p /var/cache/vmbuilder/.hoorex/15.0
# HOOREX_DB could be set at the command line to match any special location we
# want e.g.
#     HOOREX_DB=/var/cache/vmbuilder/.hoorex/15.0 vmbremovepkg apackage
# but it's probably better/easier to set it in /etc/default/vmbinstallpkg.
# If not set there or left unset, set it here and copy to REPODATA_DIR.
#
[ -z "$HOOREX_DB" ] && HOOREX_DB=$HOME/.local/share/hoorex


download_repoData() {
# $1 should be source of latest repoData - some network location
# $2 should be destination for the new repoData
  #echo "download_repoData(): downloading data from $1 into $2"
  if [ -d "$2" ]; then
    cd "$2" || {
      mkdir -p "$2"
      cd "$2" || {
        echo "Can't cd into $2. Exiting now"
        exit 1
      }
    }
  fi
  #curl --silent -O "$HOOREX_DB"/repoData.stamp -O "$HOOREX_DB"/repoData.pkl
  curl -O "$HOOREX_DB"/repoData.stamp -O "$HOOREX_DB"/repoData.pkl
}
check_download_repoData() {
# $1 should be source of latest repoData - some network location
# $2 should be  pre-check destination for the downloaded repoData
# $3 should be post-check destination for the new repoData
  #echo "check_download_repoData(): downloading data from $1 into $2"
  if [ -d "$2" ]; then
    cd "$2" || {
      mkdir -p "$2"
      cd "$2" || {
        echo "Can't cd into $2. Exiting now"
        exit 1
      }
    }
  fi
  #curl --silent -O "$HOOREX_DB"/repoData.stamp
  curl -O "$HOOREX_DB"/repoData.stamp

  # Check whether new repoData is more recent that what we already have (in $3)
  local cur_stamp new_stamp
  cur_stamp=$(cat "$REPODATA_DIR"/repoData.stamp)
  new_stamp=$(cat "$2"/repoData.stamp)
  #echo "cur_stamp = $cur_stamp, new_stamp = $new_stamp"
  if (( $(echo "$new_stamp > $cur_stamp" |bc -l) )); then
    echo "Updating dependencies!"
    if [ -d "$3" ]; then
      cd "$3" || {
        echo "Can't cd into  $3. Exiting now"
        exit 1
      }
    fi
    #curl --silent -O "$HOOREX_DB"/repoData.stamp -O "$HOOREX_DB"/repoData.pkl
    curl -O "$HOOREX_DB"/repoData.stamp -O "$HOOREX_DB"/repoData.pkl
    echo "repoData updated"
  else
    echo "Current repoData is already up to date"
    touch "$REPODATA_DIR"/repoData.stamp
  fi
}


if [ "$TARGETPKG" = "-v" ] || [ "$TARGETPKG" = "--version" ]; then
  echo "$VERSION"
  exit
fi

# If repoData update forced at command line, just do it
# directly to REPODATA_DIR
if [ "$TARGETPKG" = "-f" ] || [ "$TARGETPKG" = "--force-update" ]; then
  if [[ "$HOOREX_DB" == "http"* ]]; then
    download_repoData "$HOOREX_DB" "$REPODATA_DIR"

    # Confirm download was OK
    if [ -f "$REPODATA_DIR"/repoData.pkl ] && [ -f "$REPODATA_DIR"/repoData.stamp ]; then
      echo "Updated OK"
      exit 0
    else
      echo "Attempted update failed - $REPODATA_DIR/repoData.pkl or $REPODATA_DIR/repoData.stamp is missing after forced update"
      exit 1
    fi
  else
    echo "Don't know where to update repoData from. Set HOOREX_DB in /etc/defaults/vmbinstallpkg"
    echo "Exiting now"
    exit 2
  fi
  #exit
fi

# If repoData originates remotely, check our local version is synced with it
#
if [[ "$HOOREX_DB" == "http"* ]]; then

  if [ -f "$REPODATA_DIR"/repoData.pkl ] && [ -f "$REPODATA_DIR"/repoData.stamp ]; then
    # We have repoData already but don't download every time - only if last download > 24hrs ago
    [[ $(date +%s -r "$REPODATA_DIR"/repoData.stamp) -lt $(date +%s --date="$REPODATA_AGE_CHECK") ]] && {
      echo "Refreshing repoData"
      check_download_repoData "$HOOREX_DB" "$TEMP_REPODATA_DIR" "$REPODATA_DIR"
    }
  else
    # We don't have repoData.stamp so download it
    echo "No valid repoData so downloading"
    download_repoData "$HOOREX_DB" "$REPODATA_DIR"
  fi
else
  # Not network based i.e. using some local directory already loaded with repoData.{pkl,stamp}
  # and that directory specified in /etc/default/vmbinstallpkg or in environment

  # If HOOREX_DB has a relative address, it is relative to HooRex's default ($HOME/.local/share/hoorex)
  if [[ ! "$HOOREX_DB" = "/"* ]]; then
      echo "Relative"
    REPODATA_DIR=$HOME/.local/share/hoorex/$HOOREX_DB
  else
    echo "Absolute"
    REPODATA_DIR=$HOOREX_DB
  fi
fi

# Is REPODATA_DIR populated with something?
#
[ ! -f "$REPODATA_DIR/repoData.pkl" ] || [ ! -f "REPODATADIR_DIR/repoData.stamp" ] || {
  echo "        !!! ERROR !!! REPODATA_DIR is not populated correctly"
  echo "        Please set HOOREX_DB in /etc/default/vmbinstallpkg or set at the command line"
  echo "        HOOREX_DB should be set to the path of the directory containing existing hoorex database"
  echo "            or a remote location accessed by http"
  exit 3
}
#echo "REPODATA_DIR = $REPODATA_DIR"


# !!! Unlike vmbinstallpkg !!!
# (where REPODIR is set to some directory or remote location containing installable packages)
# REPODIR is set to Slackware's installed packages directory.
#
REPODIR=/var/lib/pkgtools/packages


# Look for target's dependent packages
#
#echo "Checking availability of $TARGETPKG and its dependencies."
arr=()
arr_not_found=()
DEPS=$(${HOOREX} -r1 -p "$REPODATA_DIR" "$TARGETPKG")
for dep in $DEPS ; do
  echo -n "Checking $dep ... "
  found_dep=false
  for app in $(cd "$REPODIR" && ls); do
    # First find a loose match (do filenames start the same way?)
    if [[ "$app" == "$dep"* ]]; then
      # Now confirm exact match
      shortname="$(basename "$app" | rev | cut -d '-' -f 4- | rev)";
      if [ "$shortname" = "$dep" ]; then
        # We have target package available
        arr+=( "$app" )
        found_dep=true
        continue
      fi
    fi
  done
  if ! $found_dep ; then
    arr_not_found+=( "$dep" )
    echo "NOT FOUND"
  else
    echo OK
  fi
done
#echo "Have ${#arr[*]} packages to display"
if [ "${#arr[*]}" = "0" ]; then
  echo "No packages to remove. Exiting now ..."
  exit 0
fi

# Generate input list for dialog
rm -f "$VMB_TEMPDIR"/dialog.tmp
echo -n "dialog --title  \"Slackware $SL_RELEASE Packages to remove\" --checklist \"Choose packages to Remove\" 19 70 13 " >"$VMB_TEMPDIR"/dialog.tmp
for i in "${arr[@]}" ; do
  shortname=$(basename "$i" | rev | cut -d '-' -f 4- | rev);

  # First check whether any other installed packages depend on this one
  REQUIREDBY=$(${HOOREX} -I -p "$REPODATA_DIR" "$shortname")

  # REQUIREDBY contains _all_ installed apps which depend on $i
  # (not just the target app)
  #
  # If any of REQUIREDBY do not appear in target's DEPS,
  # (something outside this app needs it)
  #   list $i with checkbox not checked
  # else
  #   list $i with checkbox checked

  for rqdby in $REQUIREDBY ; do
    external_requirement=false
    if ! echo "$DEPS" | grep -q "$rqdby" ; then
      # This installed dependent app is also a dependency of some
      # other installed app i.e. since used elsewhere, don't remove it
      if [[ "$rqdby" != *"Warning"* ]]; then
        echo "$i needed elsewhere (by, at least, $rqdby) so don't checkbox for removal"
      fi
      external_requirement=true
      break
      fi
  done
  if [ "$external_requirement" == true ]; then
    echo -n "$i \"\" off " >> "$VMB_TEMPDIR"/dialog.tmp ;
  else
    echo -n "$i \"\" on " >> "$VMB_TEMPDIR"/dialog.tmp ;
  fi

done

# Display dialog
#
. "$VMB_TEMPDIR"/dialog.tmp 2>"$VMB_TEMPDIR"/error.log

# Process dialog result
#
for i in $(tr -d \" < "$VMB_TEMPDIR"/error.log) ; do
  printf 'Removing %s\n' "$REPODIR/$i"
  sudo /sbin/removepkg --terse "$REPODIR"/"$i"
done

# Cleanup
[ "$VMB_TEMPDIR" = "/" ] || {
  #echo "delete $VMB_TEMPDIR"
  rm -rf "$VMB_TEMPDIR"
}

