#!/usr/bin/env bash
###############################################################################
# BRLTTY - A background process providing access to the console screen (when in
#          text mode) for a blind person using a refreshable braille display.
#
# Copyright (C) 1995-2022 by The BRLTTY Developers.
#
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
#
# This is free software, placed under the terms of the
# GNU Lesser General Public License, as published by the Free Software
# Foundation; either version 2.1 of the License, or (at your option) any
# later version. Please see the file LICENSE-LGPL for details.
#
# Web Page: http://brltty.app/
#
# This software is maintained by Dave Mielke <dave@mielke.cc>.
###############################################################################

set -e
. "$(dirname "${0}")/../brltty-prologue.sh"

if [ -x /usr/bin/dnf ]
then
   packageManager="dnf"
elif [ -x /usr/bin/dpkg ]
then
   packageManager="dpkg"
elif [ -x /usr/sbin/pkg ]
then
   packageManager="pkg"
else
   semanticError "unknown package manager"
fi

case "${packageManager}"
in
   dnf)
      platformName="fedora"
      ;;

   dpkg)
      if [ "$(uname -s)" = "GNU" ]
      then
         platformName="hurd"
      else
         platformName="debian"
      fi
      ;;

   pkg)
      platformName="freebsd"
      ;;

   *) semanticError "unknown host platform: ${packageManager}";;
esac

requiredPackageNames=()
addRequiredPackage() {
   local name="${1}"

   [ -n "${name}" ] || return 0
   [ "${name:0:1}" = "#" ] && return 0

   requiredPackageNames[${#requiredPackageNames[*]}]="${name}"
}

processExtraProgramParameters() {
   local package

   if [ "${#}" -gt 0 ]
   then
      for package
      do
         addRequiredPackage ${package}
      done
   else
      local file="${programDirectory}/${programName}.${platformName}"
      [ -e "${file}" ] || semanticError "platform package list not found: ${file}"
      [ -f "${file}" ] || semanticError "not a file: ${file}"
      [ -r "${file}" ] || semanticError "platform package list not readable: ${file}"

      while read package
      do
         addRequiredPackage ${package}
      done < <(cat "${file}")
   fi

   [ "${#requiredPackageNames[@]}" -gt 0 ] || semanticError "empty package list"
}

addProgramOption i flag installNeededPackages "install the needed packages"
addProgramOption l flag listNeededPackages "list the needed packages"
optionalProgramParameters
parseProgramArguments "${@}"

listInstalledPackages_dnf() {
   rpm --query --all --queryformat '%{NAME}\n'
}

installPackages_dnf() {
   dnf -y --quiet install "${@}"
}

listInstalledPackages_dpkg() {
   dpkg-query --show --showformat '${Package}\n'
}

installPackages_dpkg() {
   apt --yes --quiet --quiet --quiet install "${@}"
}

listInstalledPackages_pkg() {
   pkg query --all "%n"
}

installPackages_pkg() {
   pkg --quiet install "${@}"
}

normalizePackageList() {
   sort | uniq
}

listInstalledPackages() {
   "listInstalledPackages_${packageManager}"
}

listRequiredPackages() {
   local name

   for name in "${requiredPackageNames[@]}"
   do
      echo "${name}"
   done
}

neededPackages=(
   $(
      diff <(listInstalledPackages | normalizePackageList) \
           <(listRequiredPackages | normalizePackageList) |
      sed -n -e 's/^> //p'
   )
)

if [ "${#neededPackages[@]}" -gt 0 ]
then
   logMessage task "packages needed: ${#neededPackages[@]}"

   "${listNeededPackages}" && {
      for package in "${neededPackages[@]}"
      do
         echo "${package}"
      done
   }

   "${installNeededPackages}" && {
      "installPackages_${packageManager}" "${neededPackages[@]}"
   }
else
   logMessage task "no needed packages"
fi

exit 0
