#!/bin/bash
#
# compat32ctl - install, update and remove AlienBOB's compat32 package
#               collection on Slackware64 -current.
#
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# 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 General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <https://www.gnu.org/licenses/>.
#
set -euo pipefail

REPO_URL="${REPO_URL:-https://slackware.nl/people/alien/multilib/current}"
MIRROR_DIR="${MIRROR_DIR:-/var/cache/compat32}"
PKGDIR="${PKGDIR:-/var/log/packages}"

DRY_RUN=0
PROG="${0##*/}"

usage() {
  cat <<EOF
Usage: $PROG <command> [-n|--dry-run]

Commands:
  sync      Download/refresh the compat32 tree and verify its checksums
  install   Sync, then install or upgrade compat32-tools and every -compat32 package
  update    Same as install (kept as a distinct verb for intent)
  remove    Remove every installed compat32 package

Options:
  -n, --dry-run   Show the commands that would run without executing them
  -h, --help      Show this help

Environment:
  REPO_URL     Remote tree to sync (default: $REPO_URL)
  MIRROR_DIR   Local package cache    (default: $MIRROR_DIR)
  PKGDIR       Installed-package db   (default: $PKGDIR)
EOF
}

die() {
  printf '%s: %s\n' "$PROG" "$*" >&2
  exit 1
}

require_cmd() {
  [ "$DRY_RUN" -eq 1 ] && return 0
  command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
}

require_root() {
  [ "$DRY_RUN" -eq 1 ] && return 0
  [ "$(id -u)" -eq 0 ] || die "must be run as root (or use --dry-run to preview)"
}

run() {
  if [ "$DRY_RUN" -eq 1 ]; then
    printf '+ %s\n' "$*"
  else
    "$@"
  fi
}

mirror_and_verify() {
  require_cmd lftp
  require_cmd md5sum
  require_root
  printf '==> Syncing %s -> %s\n' "$REPO_URL" "$MIRROR_DIR"
  run mkdir -p "$MIRROR_DIR"
  run lftp -c "set cmd:show-status on; open $REPO_URL; mirror -c -e -v . $MIRROR_DIR"
  printf '==> Verifying checksums\n'
  if [ "$DRY_RUN" -eq 1 ]; then
    printf '+ cd %s && md5sum -c --ignore-missing CHECKSUMS.md5\n' "$MIRROR_DIR"
  else
    ( cd "$MIRROR_DIR" && md5sum -c --ignore-missing CHECKSUMS.md5 )
  fi
}

do_install() {
  require_cmd upgradepkg
  mirror_and_verify
  printf '==> Installing or upgrading compat32 packages\n'
  run upgradepkg --install-new "$MIRROR_DIR"/compat32-tools-*.tgz
  run upgradepkg --install-new "$MIRROR_DIR"/slackware64-compat32/*-compat32/*.t?z
}

do_remove() {
  require_cmd removepkg
  require_root
  local pkg names=()
  for pkg in "$PKGDIR"/*compat32*; do
    [ -e "$pkg" ] || continue
    names+=("${pkg##*/}")
  done
  if [ "${#names[@]}" -eq 0 ]; then
    printf 'No installed compat32 packages found.\n'
    return 0
  fi
  printf '==> Removing %d compat32 package(s)\n' "${#names[@]}"
  run removepkg "${names[@]}"
}

main() {
  if [ "$#" -lt 1 ]; then
    usage >&2
    exit 1
  fi

  local cmd="$1"
  shift

  case "$cmd" in
    -h|--help|help)
      usage
      exit 0
      ;;
  esac

  while [ "$#" -gt 0 ]; do
    case "$1" in
      -n|--dry-run) DRY_RUN=1 ;;
      -h|--help) usage; exit 0 ;;
      *) die "unknown option: $1" ;;
    esac
    shift
  done

  case "$cmd" in
    sync)    mirror_and_verify ;;
    install) do_install ;;
    update)  do_install ;;
    remove)  do_remove ;;
    *)       usage >&2; die "unknown command: $cmd" ;;
  esac
}

if [ "${BASH_SOURCE[0]}" = "$0" ]; then
  main "$@"
fi
