# Use emacs key bindings
bindkey -e

# Meta/UTF-8 settings
setopt COMBINING_CHARS

# History configuration
HISTFILE=~/.zsh_history
HISTSIZE=32768
SAVEHIST=32768
setopt APPEND_HISTORY           # Append to history file
setopt SHARE_HISTORY            # Share history across sessions
setopt HIST_IGNORE_DUPS         # Ignore duplicate commands
setopt HIST_IGNORE_ALL_DUPS     # Remove older duplicate from history
setopt HIST_IGNORE_SPACE        # Ignore commands starting with space
setopt HIST_REDUCE_BLANKS       # Remove unnecessary blanks
setopt HIST_VERIFY              # Don't execute immediately upon history expansion

# Completion configuration
setopt COMPLETE_IN_WORD         # Complete from both ends of word
setopt ALWAYS_TO_END            # Move cursor to end after completion
unsetopt MENU_COMPLETE          # Don't jump into menu selection on first tab
unsetopt BASH_AUTO_LIST         # Let AUTO_LIST below list immediately when ambiguous
setopt AUTO_LIST                # List choices when completion is ambiguous
setopt LIST_AMBIGUOUS           # Insert any shared prefix before listing choices
setopt AUTO_MENU                # Enter menu selection on repeated tab after listing

# Initialize the zsh completion system. The _omarchy completion ships to
# /usr/share/zsh/site-functions/, which is on the default fpath.
autoload -Uz compinit
compinit -i

# zsh/complist provides the menuselect keymap and the highlighted
# interactive completion menu (enabled below via `menu select`).
zmodload zsh/complist

# Directory navigation
setopt AUTO_CD                  # cd by typing directory name
setopt CHASE_LINKS              # Mark symlinked directories

# Case-insensitive completion
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=* l:|=*'

# Interactive menu with the current selection highlighted.
zstyle ':completion:*' menu select

# Populate LS_COLORS so completion listings (and ls) get colors. Coreutils
# `ls` falls back to built-in defaults, but the list-colors zstyle below
# needs LS_COLORS to be exported.
if [[ -z $LS_COLORS ]] && (( $+commands[dircolors] )); then
  eval "$(dircolors -b)"
fi

# Colored completion listings
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"

# Use the column-grid completion layout (filenames only). Defensively delete
# any prior `file-list` style so re-sourcing on top of an older system copy
# of zoptions (e.g. via dev-link) doesn't leave the verbose ls -l listing.
zstyle -d ':completion:*' file-list

# Show all completions at once (no paging)
zstyle ':completion:*' list-prompt ''
zstyle ':completion:*' select-prompt ''

# Don't complete hidden files unless explicitly starting with dot
zstyle ':completion:*' match-hidden-files off

# Hide individual omarchy-* binaries from initial-word command completion;
# the unified `omarchy` dispatcher is the user-facing entry point.
zstyle ':completion:*:-command-:*' ignored-patterns 'omarchy-*'

# Don't complete shell variables anywhere in Tab completion. The Ctrl+Alt+V
# fzf widget remains available for intentionally inserting variables.
_parameters() { return 1 }

# Arrow keys: history search matching current input
bindkey "^[[A" history-search-backward
bindkey "^[[B" history-search-forward
bindkey "^[[C" forward-char
bindkey "^[[D" backward-char

# Omarchy command routes should feel like bash menu completion: typing a
# partial route such as `omarchy br<Tab>` inserts the first route match
# (`branch `), while repeated Tabs enter zsh's highlighted completion menu
# and cycle through the same sibling matches. Empty-prefix completions such
# as `omarchy <Tab>` fall back to zsh's normal completion listing.
typeset -gi _omarchy_tab_route_active=0

_omarchy-route-complete-or-expand() {
  emulate -L zsh
  setopt extended_glob
  unsetopt beep

  local trigger="${FZF_COMPLETION_TRIGGER-'**'}"
  if [[ -n $trigger && $LBUFFER == *$trigger && ${+widgets[fzf-completion]} -eq 1 ]]; then
    zle fzf-completion
    return $?
  fi

  if [[ $LASTWIDGET == _omarchy-route-complete-or-expand && $_omarchy_tab_route_active -eq 1 ]]; then
    setopt auto_list
    zstyle ':completion:*' menu select
    zle menu-complete
    zle menu-select
    return $?
  fi

  _omarchy_tab_route_active=0

  if [[ -z $RBUFFER && $LBUFFER == omarchy[[:space:]]* && $LBUFFER != *[[:space:]] ]]; then
    local current="${LBUFFER##*[[:space:]]}"
    if [[ -n $current && $current != -* ]]; then
      unsetopt auto_list bash_auto_list
      zstyle ':completion:*' menu yes
      zle menu-complete
      _omarchy_tab_route_active=1
      return $?
    fi
  fi

  setopt auto_list
  zstyle ':completion:*' menu select
  zle expand-or-complete
}
zle -N _omarchy-route-complete-or-expand

_omarchy-bind-tab-completion() {
  bindkey '^I' _omarchy-route-complete-or-expand
}
_omarchy-bind-tab-completion

# fzf's zsh completion script is loaded later by shell/inits and also binds
# Tab. Re-apply Omarchy's Tab widget after startup; the widget above still
# delegates to fzf when the configured fzf trigger (default: **) is present.
autoload -Uz add-zsh-hook
add-zsh-hook precmd _omarchy-bind-tab-completion

# Shift-Tab cycles the completion menu backwards. The main-keymap binding
# kicks in on the first press; the menuselect binding handles subsequent
# presses once the highlighted menu is active.
bindkey '^[[Z' reverse-menu-complete
bindkey -M menuselect '^[[Z' reverse-menu-complete

# Extended globbing
setopt EXTENDED_GLOB

# Don't beep on errors
unsetopt BEEP

# Allow comments in interactive shells
setopt INTERACTIVE_COMMENTS

# Color man pages with bat
export MANROFFOPT="-c"
export MANPAGER="sh -c 'col -bx | bat -l man -p'"

# Ensure mise works (disable command hashing)
setopt NO_HASH_CMDS
setopt NO_HASH_DIRS

# fzf ZLE widgets
if command -v fzf &>/dev/null; then
  # fzf file/directory search widget (Ctrl+Alt+F)
  fzf-file-widget() {
    local fd_cmd=$(command -v fdfind || command -v fd || echo "fd")
    local current_token="${LBUFFER##* }"
    local expanded_token=""
    if [[ -n "$current_token" ]]; then
      expanded_token=$(eval echo "$current_token" 2>/dev/null || echo "$current_token")
    fi

    local selected
    if [[ "$expanded_token" == */ ]] && [[ -d "$expanded_token" ]]; then
      selected=$($fd_cmd --color=always --base-directory="$expanded_token" 2>/dev/null | \
        fzf --multi --ansi --prompt="Directory $expanded_token> " \
          --preview="[[ -d $expanded_token{} ]] && ls -lah $expanded_token{} || bat --color=always --style=numbers $expanded_token{} 2>/dev/null || cat $expanded_token{}")
      [[ -n "$selected" ]] && selected="${expanded_token}${selected}"
    else
      selected=$($fd_cmd --color=always 2>/dev/null | \
        fzf --multi --ansi --prompt="Directory> " --query="$expanded_token" \
          --preview="[[ -d {} ]] && ls -lah {} || bat --color=always --style=numbers {} 2>/dev/null || cat {}")
    fi

    if [[ -n "$selected" ]]; then
      selected=$(printf '%q' "$selected")
      LBUFFER="${LBUFFER%$current_token}${selected} "
    fi
    zle reset-prompt
  }
  zle -N fzf-file-widget
  bindkey '^[^F' fzf-file-widget  # Ctrl+Alt+F

  # fzf git log search widget (Ctrl+Alt+L)
  fzf-git-log-widget() {
    if ! git rev-parse --git-dir >/dev/null 2>&1; then
      echo "Not in a git repository." >&2
      return 1
    fi

    local selected
    selected=$(git log --no-show-signature --color=always \
      --format='%C(bold blue)%h%C(reset) - %C(cyan)%ad%C(reset) %C(yellow)%d%C(reset) %C(normal)%s%C(reset)  %C(dim normal)[%an]%C(reset)' \
      --date=short | \
      fzf --ansi --multi --scheme=history --prompt="Git Log> " \
        --preview='git show --color=always --stat --patch {1}' \
        --preview-window=right:50%:wrap | \
      awk '{print $1}' | \
      xargs -I {} git rev-parse {} 2>/dev/null | \
      tr '\n' ' ')

    if [[ -n "$selected" ]]; then
      LBUFFER="${LBUFFER}${selected}"
    fi
    zle reset-prompt
  }
  zle -N fzf-git-log-widget
  bindkey '^[^L' fzf-git-log-widget  # Ctrl+Alt+L

  # fzf variables search widget (Ctrl+Alt+V)
  fzf-variables-widget() {
    local current_token="${LBUFFER##* }"
    local cleaned_token="${current_token#\$}"

    local selected
    selected=$(typeset -p | awk '{print $1, $2}' | sort -u | awk '{print $2}' | \
      fzf --multi --prompt="Variables> " --preview-window=wrap \
        --preview='echo {} && typeset -p {} 2>/dev/null || echo "No details available"' \
        --query="$cleaned_token")

    if [[ -n "$selected" ]]; then
      if [[ "$current_token" == \$* ]]; then
        selected="\$${selected}"
      fi
      LBUFFER="${LBUFFER%$current_token}${selected} "
    fi
    zle reset-prompt
  }
  zle -N fzf-variables-widget
  bindkey '^[^V' fzf-variables-widget  # Ctrl+Alt+V
fi

# Plugins (shipped via the omarchy-zsh package's depends list).
#
# zsh-syntax-highlighting: colors valid commands as you type. MUST be
# sourced last so it sees every previously-defined ZLE widget — adding
# anything below this line will skip highlighting for that widget.
[[ -f /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]] && \
  source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
