#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
# Copyright (c) 2015-2026 Sebastien Rousseau
## `dot completion <bash|zsh|fish|nu>` — emit shell completion for `dot`,
## generated from the canonical _dot_help_specs registry in bin/dot. Using one
## source of truth keeps all four shells in sync (the previously hand-maintained
## fish/nushell lists drifted and referenced non-existent commands).
##
## Usage:
##   dot completion bash  >> ~/.bashrc.d/dot.bash
##   dot completion zsh   > "${fpath[1]}/_dot"
##   dot completion fish  > ~/.config/fish/completions/dot.fish
##   dot completion nu    >> ~/.config/nushell/completions.nu

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=../../../lib/dot/utils.sh
source "$SCRIPT_DIR/../../../lib/dot/utils.sh"

_completion_dot_cli() {
  local src
  src="$(resolve_source_dir)"
  printf '%s/bin/dot\n' "$src"
}

# Emit "name<TAB>description" for every top-level command (a _dot_help_specs
# field-2 entry with no space; entries containing a space are subcommands).
# Strip ": ' from descriptions so they can't break any shell's quoting.
_completion_commands() {
  local cli
  cli="$(_completion_dot_cli)"
  awk -F'|' '
    /_dot_help_specs\(\)/ { in_func = 1; next }
    in_func && /cat <<'\''EOF'\''/ { in_block = 1; next }
    in_block && /^EOF$/ { exit }
    in_block && NF >= 3 && $2 !~ / / {
      name = $2; desc = $3
      gsub(/^[ \t]+|[ \t]+$/, "", name)
      gsub(/^[ \t]+|[ \t]+$/, "", desc)
      gsub(/[":\047]/, "", desc)
      if (name != "") print name "\t" desc
    }
  ' "$cli"
}

# Emit "parent<TAB>child<TAB>description" for every subcommand (a field-2
# entry that contains a space, e.g. "theme list" -> parent=theme child=list).
_completion_subcommands() {
  local cli
  cli="$(_completion_dot_cli)"
  awk -F'|' '
    /_dot_help_specs\(\)/ { in_func = 1; next }
    in_func && /cat <<'\''EOF'\''/ { in_block = 1; next }
    in_block && /^EOF$/ { exit }
    in_block && NF >= 3 && $2 ~ / / {
      full = $2; desc = $3
      gsub(/^[ \t]+|[ \t]+$/, "", full)
      gsub(/^[ \t]+|[ \t]+$/, "", desc)
      gsub(/[":\047]/, "", desc)
      parent = full; sub(/ .*/, "", parent)
      child = full; sub(/^[^ ]+ /, "", child)
      if (parent != "" && child != "") print parent "\t" child "\t" desc
    }
  ' "$cli"
}

gen_bash() {
  local names
  names="$(_completion_commands | cut -f1 | tr '\n' ' ')"
  printf '# dot bash completion — generated by: dot completion bash\n'
  printf "complete -W '%s' dot\n" "${names% }"
}

gen_zsh() {
  local name desc
  printf '#compdef dot\n# generated by: dot completion zsh\n'
  printf '_dot() {\n  local -a commands\n  commands=(\n'
  while IFS=$'\t' read -r name desc; do
    printf "    '%s:%s'\n" "$name" "$desc"
  done < <(_completion_commands)
  printf '  )\n  _describe '\''command'\'' commands\n}\n_dot "$@"\n'
}

gen_fish() {
  local name desc
  printf '# dot fish completion — generated by: dot completion fish\n'
  printf 'complete -c dot -f\n'
  while IFS=$'\t' read -r name desc; do
    printf 'complete -c dot -n "__fish_use_subcommand" -a %s -d "%s"\n' "$name" "$desc"
  done < <(_completion_commands)
  local parent child
  while IFS=$'\t' read -r parent child desc; do
    printf 'complete -c dot -n "__fish_seen_subcommand_from %s" -a %s -d "%s"\n' \
      "$parent" "$child" "$desc"
  done < <(_completion_subcommands)
}

gen_nu() {
  local name desc
  printf '# dot nushell completion — generated by: dot completion nu\n'
  printf 'export extern dot [\n  command?: string@dot_commands\n  ...args: string\n]\n'
  printf 'def dot_commands [] {\n  [\n'
  while IFS=$'\t' read -r name desc; do
    printf '    { value: "%s", description: "%s" }\n' "$name" "$desc"
  done < <(_completion_commands)
  printf '  ]\n}\n'
}

usage() {
  cat <<'USAGE'
Usage: dot completion <bash|zsh|fish|nu>

Generate shell completion for `dot` from the canonical command registry.

  dot completion bash  >> ~/.bashrc.d/dot.bash
  dot completion zsh   > "${fpath[1]}/_dot"
  dot completion fish  > ~/.config/fish/completions/dot.fish
  dot completion nu    >> ~/.config/nushell/completions.nu
USAGE
}

# Dispatch: $1 is the command name ("completion"); $2 is the target shell.
case "${2:-}" in
  bash) gen_bash ;;
  zsh) gen_zsh ;;
  fish) gen_fish ;;
  nu | nushell) gen_nu ;;
  "" | -h | --help | help) usage ;;
  *)
    echo "dot completion: unknown shell '${2}' (want: bash|zsh|fish|nu)" >&2
    exit 1
    ;;
esac
