#!/bin/bash

# omarchy:summary=Pick one or multiple options from a menu
# omarchy:group=menu
# omarchy:name=select
# omarchy:args=prompt [option...] [-- --multiple --selected <value> --on-change <command-json> --change-key <key> --width <pixels> --maxheight <pixels>]
# omarchy:examples=omarchy menu select Format jpg png|omarchy-menu-select Resolution 4k 1080p 720p -- --width 400

# An option may lead with an icon, as "<glyph><TAB><label>", and may trail a
# subtext shown under the label, as "<glyph><TAB><label><TAB><subtext>". The
# menu shows the glyph but never returns it. A plain option returns the label
# alone; an option with a subtext returns "<label><TAB><subtext>", so callers
# with same-named rows get the subtext back as the stable key.

# With --multiple, clicking/Enter toggles rows and Apply returns a JSON array.
# --on-change takes a JSON command array; each toggle runs it with the selection
# JSON appended, applies immediately, and needs no Apply row. A successful
# command may print a JSON array of actual selections to update the checkmarks.
# --selected takes a returned value (label plus any subtext), and can be repeated.

set -euo pipefail

if (( $# < 1 )); then
  echo "Usage: omarchy-menu-select <prompt> [option...] [-- menu args...]" >&2
  exit 1
fi

prompt="$1"
shift

options=()
menu_width=""
menu_maxheight=""
multiple=0
on_change="[]"
change_key=""
selected=()

while (( $# > 0 )); do
  if [[ $1 == "--" ]]; then
    shift
    while (( $# > 0 )); do
      case "$1" in
        --on-change)
          shift
          if (( $# == 0 )); then
            echo "omarchy-menu-select: --on-change requires a JSON command array" >&2
            exit 1
          fi
          on_change="$1"
          ;;
        --change-key)
          shift
          if (( $# == 0 )); then
            echo "omarchy-menu-select: --change-key requires a value" >&2
            exit 1
          fi
          change_key="$1"
          ;;
        --multiple)
          multiple=1
          ;;
        --selected)
          shift
          if (( $# == 0 )); then
            echo "omarchy-menu-select: --selected requires a value" >&2
            exit 1
          fi
          selected+=("$1")
          ;;
        --width)
          shift
          if (( $# == 0 )); then
            echo "omarchy-menu-select: --width requires a value" >&2
            exit 1
          fi
          menu_width="$1"
          ;;
        --height|--maxheight)
          arg="$1"
          shift
          if (( $# == 0 )); then
            echo "omarchy-menu-select: $arg requires a value" >&2
            exit 1
          fi
          menu_maxheight="$1"
          ;;
      esac
      shift
    done
    break
  fi

  options+=("$1")
  shift
done

if (( ${#options[@]} == 0 )) && [[ ! -t 0 ]]; then
  mapfile -t options
fi

if (( ${#options[@]} == 0 )); then
  echo "Usage: omarchy-menu-select <prompt> [option...] [-- menu args...]" >&2
  exit 1
fi

selection_file=$(mktemp)
done_file=$(mktemp)
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT

options_json=$(perl -MEncode=decode -MJSON::PP=encode_json -e 'print encode_json([map { decode("UTF-8", $_) } @ARGV])' "${options[@]}")
selected_json=$(perl -MEncode=decode -MJSON::PP=encode_json -e 'print encode_json([map { decode("UTF-8", $_) } @ARGV])' "${selected[@]}")
payload=$(perl -MEncode=decode -MJSON::PP=encode_json,decode_json -e '
  my $payload = {
    mode => "select",
    prompt => decode("UTF-8", $ARGV[0]),
    options => decode_json($ARGV[1]),
    multiple => $ARGV[6] ? JSON::PP::true : JSON::PP::false,
    selected => decode_json($ARGV[7]),
    onChange => decode_json($ARGV[8]),
    changeKey => $ARGV[9],
    selectionFile => decode("UTF-8", $ARGV[2]),
    doneFile => decode("UTF-8", $ARGV[3])
  };
  $payload->{width} = int($ARGV[4]) if length($ARGV[4] // "");
  $payload->{maxHeight} = int($ARGV[5]) if length($ARGV[5] // "");
  print encode_json($payload)
' "$prompt" "$options_json" "$selection_file" "$done_file" "$menu_width" "$menu_maxheight" "$multiple" "$selected_json" "$on_change" "$change_key")

omarchy-shell shell summon omarchy.menu "$payload" >/dev/null || exit 2

while [[ ! -e $done_file ]]; do
  sleep 0.05
done

if [[ -s $selection_file ]]; then
  cat "$selection_file"
else
  exit 1
fi
