_polybar_default_file() {
  local suffix=/polybar/config.ini

  local home_path=${XDG_CONFIG_HOME:-$HOME/.config}${suffix}
  local etc_xdg_path=${XDG_CONFIG_DIRS:-/etc/xdg}${suffix}
  local etc_path=/etc${suffix}

  if [ -r "$home_path" ]; then
    echo "$home_path"
  elif [ -r "$etc_xdg_path" ]; then
    echo "$etc_xdg_path"
  elif [ -r "$etc_path" ]; then
    echo "$etc_path"
  fi
}

_polybar_config_file() {
  for ((i = 0; i < COMP_CWORD; i++)); do
    case ${COMP_WORDS[i]} in
    --config)
      echo "${COMP_WORDS[i + 2]}"
      return
      ;;
    -c)
      echo "${COMP_WORDS[i + 1]}"
      return
      ;;
    esac
  done

  _polybar_default_file
}

_polybar_bars() {
  local config_file=$(_polybar_config_file)

  if [ -r "$config_file" ]; then
    sed -nE 's|[[:space:]]*\[bar/([^\]+)\][[:space:]]*$|\1|p' "$config_file"
  fi
}

_polybar() {
  local options='-h --help
                 -v --version
                 -l --log=
                 -q --quiet
                 -c --config=
                 -r --reload
                 -d --dump=
                 -m --list-monitors
                 -M --list-all-monitors
                 -w --print-wmname
                 -s --stdout
                 -p --png='

  local log_levels='error
                    warning
                    notice
                    info
                    trace'

  COMPREPLY=()

  local cur=${COMP_WORDS[COMP_CWORD]}
  case "$cur" in
  -*)
    COMPREPLY=( $(compgen -W "$options" -- "$cur") )
    ;;
  *)
    local prev=${COMP_WORDS[COMP_CWORD - 1]}
    if [ "$prev" = "=" ]; then
      prev=${COMP_WORDS[COMP_CWORD - 2]}
    fi

    case "$prev" in
    -l|--log)
      COMPREPLY=( $(compgen -W "$log_levels" -- "$cur") )
      return 0
      ;;
    -c|--config)
      COMPREPLY=( $(compgen -f "$cur") )
      return 0
      ;;
    -p|--png)
      COMPREPLY=( $(compgen -f -X "!*.png" "$cur") )
      return 0
      ;;
    -d|--dump)
      return 0
      ;;
    *)
      COMPREPLY=( $(compgen -W "$options $(_polybar_bars)" -- "$cur") )
      ;;
    esac
  esac

  for ((i = 0; i < ${#COMPREPLY[@]}; i++)); do
    case ${COMPREPLY[i]} in
    --*=) ;;
    -*) COMPREPLY[i]+=" "
    esac
  done

  return 0
}

complete -o filenames -o noquote -o nospace -F _polybar polybar