#!/bin/bash
# OpenMenu NX sample: create a compressed (optionally AES-256 encrypted)
# disk image from the files/folders currently selected when the menu was opened.
# OpenMenu NX passes the selection as normal positional arguments: "$@".

set -u
set -o pipefail
# OMNX_DMG_NAME_PROMPT_V1

lang="${OMNX_LANGUAGE:-${LANG:-en}}"
lang="${lang%%.*}"
lang="${lang%%_*}"
lang="${lang%%-*}"

case "$lang" in
  de)
    TXT_TITLE="OpenMenu NX – Disk Image"
    TXT_NO_SELECTION="Es sind keine Dateien oder Ordner ausgewählt."
    TXT_PASSWORD="Passwort für das Disk Image (leer = kein Passwort):"
    TXT_IMAGE_NAME="Name des Disk Images:"
    TXT_CANCEL="Abbrechen"
    TXT_NOPASS="Ohne Passwort"
    TXT_OK="OK"
    TXT_COPYING="Die ausgewählten Dateien konnten nicht vorbereitet werden."
    TXT_CREATING="Das Disk Image konnte nicht erstellt werden."
    TXT_DONE="Disk Image erstellt:"
    ;;
  es)
    TXT_TITLE="OpenMenu NX – Imagen de disco"
    TXT_NO_SELECTION="No hay archivos ni carpetas seleccionados."
    TXT_PASSWORD="Contraseña para la imagen de disco (vacía = sin contraseña):"
    TXT_IMAGE_NAME="Nombre de la imagen de disco:"
    TXT_CANCEL="Cancelar"
    TXT_NOPASS="Sin contraseña"
    TXT_OK="Aceptar"
    TXT_COPYING="No se pudieron preparar los archivos seleccionados."
    TXT_CREATING="No se pudo crear la imagen de disco."
    TXT_DONE="Imagen de disco creada:"
    ;;
  fr)
    TXT_TITLE="OpenMenu NX – Image disque"
    TXT_NO_SELECTION="Aucun fichier ou dossier n’est sélectionné."
    TXT_PASSWORD="Mot de passe de l’image disque (vide = sans mot de passe) :"
    TXT_IMAGE_NAME="Nom de l’image disque :"
    TXT_CANCEL="Annuler"
    TXT_NOPASS="Sans mot de passe"
    TXT_OK="OK"
    TXT_COPYING="Impossible de préparer les éléments sélectionnés."
    TXT_CREATING="Impossible de créer l’image disque."
    TXT_DONE="Image disque créée :"
    ;;
  it)
    TXT_TITLE="OpenMenu NX – Immagine disco"
    TXT_NO_SELECTION="Nessun file o cartella selezionato."
    TXT_PASSWORD="Password per l’immagine disco (vuota = nessuna password):"
    TXT_IMAGE_NAME="Nome dell’immagine disco:"
    TXT_CANCEL="Annulla"
    TXT_NOPASS="Senza password"
    TXT_OK="OK"
    TXT_COPYING="Impossibile preparare gli elementi selezionati."
    TXT_CREATING="Impossibile creare l’immagine disco."
    TXT_DONE="Immagine disco creata:"
    ;;
  *)
    TXT_TITLE="OpenMenu NX – Disk Image"
    TXT_NO_SELECTION="No files or folders are selected."
    TXT_PASSWORD="Password for the disk image (empty = no password):"
    TXT_IMAGE_NAME="Disk image name:"
    TXT_CANCEL="Cancel"
    TXT_NOPASS="No Password"
    TXT_OK="OK"
    TXT_COPYING="The selected items could not be prepared."
    TXT_CREATING="The disk image could not be created."
    TXT_DONE="Disk image created:"
    ;;
esac

show_alert() {
  /usr/bin/osascript - "$TXT_TITLE" "$1" <<'APPLESCRIPT' >/dev/null 2>&1
on run argv
    display alert (item 1 of argv) message (item 2 of argv) as warning
end run
APPLESCRIPT
}

if [ "$#" -eq 0 ]; then
  show_alert "$TXT_NO_SELECTION"
  exit 1
fi

# Only work with real, existing items. OpenMenu NX supplies one path per argument,
# so spaces and special characters in file names remain intact.
for source in "$@"; do
  if [ ! -e "$source" ]; then
    show_alert "$TXT_COPYING\n\n$source"
    exit 1
  fi
done

first="$1"
# Disk images are always created on the user’s Desktop, never beside the source
# item. Asking macOS for the Desktop path also respects redirected Desktop folders;
# $HOME/Desktop remains a safe fallback.
desktop_path="$(/usr/bin/osascript -e 'POSIX path of (path to desktop folder)' 2>/dev/null || true)"
if [ -n "$desktop_path" ]; then
  output_dir="${desktop_path%/}"
else
  output_dir="$HOME/Desktop"
fi
first_name="$(/usr/bin/basename "$first")"
if [ -d "$first" ]; then
  stem="$first_name"
else
  case "$first_name" in
    *.*) stem="${first_name%.*}" ;;
    *)   stem="$first_name" ;;
  esac
fi
[ -n "$stem" ] || stem="OpenMenu NX Selection"

# Use exactly the filename the former automatic behavior would have generated as
# the default value in the name dialog. The .dmg suffix is intentionally omitted.
default_name="$stem"
index=1
while [ -e "$output_dir/$default_name.dmg" ]; do
  default_name="${stem}_${index}"
  index=$((index + 1))
done

# Stage copies instead of moving the user's originals. ditto preserves macOS
# metadata/resource forks and works for both files and directories.
tmp_root="$(/usr/bin/mktemp -d "${TMPDIR:-/tmp}/OpenMenuNX-DMG.XXXXXX")" || exit 1
stage="$tmp_root/content"
/bin/mkdir -p "$stage"
cleanup() { /bin/rm -rf "$tmp_root"; }
trap cleanup EXIT INT TERM HUP

unique_destination() {
  local name="$1"
  local candidate="$stage/$name"
  local n=1
  if [ ! -e "$candidate" ]; then
    printf '%s\n' "$candidate"
    return
  fi
  local base="$name"
  local ext=""
  if [[ "$name" == *.* && "$name" != .* ]]; then
    base="${name%.*}"
    ext=".${name##*.}"
  fi
  while [ -e "$stage/${base}_${n}${ext}" ]; do
    n=$((n + 1))
  done
  printf '%s\n' "$stage/${base}_${n}${ext}"
}

for source in "$@"; do
  dest="$(unique_destination "$(/usr/bin/basename "$source")")"
  if ! /usr/bin/ditto "$source" "$dest"; then
    show_alert "$TXT_COPYING\n\n$source"
    exit 1
  fi
done

# Ask for an optional password. The password is hidden by AppleScript and is
# passed to hdiutil over stdin; it is never placed in the hdiutil command line.
prompt_result="$(/usr/bin/osascript - "$TXT_TITLE" "$TXT_PASSWORD" "$TXT_CANCEL" "$TXT_NOPASS" "$TXT_OK" <<'APPLESCRIPT'
on run argv
    set dialogResult to display dialog (item 2 of argv) with title (item 1 of argv) default answer "" with hidden answer buttons {(item 3 of argv), (item 4 of argv), (item 5 of argv)} default button (item 5 of argv) cancel button (item 3 of argv)
    set chosenButton to button returned of dialogResult
    if chosenButton is (item 4 of argv) then
        return "NOPASS"
    end if
    return "PASS" & linefeed & (text returned of dialogResult)
end run
APPLESCRIPT
)" || exit 0

mode="${prompt_result%%$'\n'*}"
password=""
if [ "$mode" = "PASS" ]; then
  if [[ "$prompt_result" == *$'\n'* ]]; then
    password="${prompt_result#*$'\n'}"
  fi
  # An empty password is intentionally equivalent to "No Password".
  [ -n "$password" ] || mode="NOPASS"
fi

# Ask for the image filename after the password choice. The default is exactly
# what OpenMenu NX would previously have generated automatically, without ".dmg".
image_name="$(/usr/bin/osascript - "$TXT_TITLE" "$TXT_IMAGE_NAME" "$TXT_CANCEL" "$TXT_OK" "$default_name" <<'APPLESCRIPT'
on run argv
    set dialogResult to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 5 of argv) buttons {(item 3 of argv), (item 4 of argv)} default button (item 4 of argv) cancel button (item 3 of argv)
    return text returned of dialogResult
end run
APPLESCRIPT
)" || exit 0

# Keep the field friendly: users enter only the base name. If they nevertheless
# type .dmg, remove it once. Slashes/colons cannot be filename separators here.
image_name="$(printf '%s' "$image_name" | /usr/bin/sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
case "$image_name" in
  *.[dD][mM][gG]) image_name="${image_name%????}" ;;
esac
image_name="${image_name//\//-}"
image_name="${image_name//:/-}"
[ -n "$image_name" ] || image_name="$default_name"

# Never overwrite an existing image, including when the user entered a custom
# name. foo.dmg -> foo_1.dmg -> foo_2.dmg ...
final_name="$image_name"
index=1
while [ -e "$output_dir/$final_name.dmg" ]; do
  final_name="${image_name}_${index}"
  index=$((index + 1))
done
out="$output_dir/$final_name.dmg"

# A direct -srcfolder create is synchronous and avoids the old mount/detach race.
# UDZO gives a read-only compressed image. With a password we request AES-256.
volname="$final_name"
if [ "$mode" = "PASS" ]; then
  if ! hdi_output="$(printf '%s' "$password" | /usr/bin/hdiutil create \
      -srcfolder "$stage" \
      -volname "$volname" \
      -format UDZO \
      -encryption AES-256 \
      -stdinpass \
      "$out" 2>&1)"; then
    show_alert "$TXT_CREATING\n\n$hdi_output"
    exit 1
  fi
else
  if ! hdi_output="$(/usr/bin/hdiutil create \
      -srcfolder "$stage" \
      -volname "$volname" \
      -format UDZO \
      "$out" 2>&1)"; then
    show_alert "$TXT_CREATING\n\n$hdi_output"
    exit 1
  fi
fi

/usr/bin/open -R "$out"
/usr/bin/osascript - "$TXT_TITLE" "$TXT_DONE" "$out" <<'APPLESCRIPT' >/dev/null 2>&1
on run argv
    display notification ((item 2 of argv) & " " & (item 3 of argv)) with title (item 1 of argv)
end run
APPLESCRIPT

exit 0
