#!/bin/zsh

### Generate the Zsh script to load a plugin.
#
# usage: antidote script [-h|--help] [-k|--kind <kind>] [-p|--path <path>]
#                        [-c|--conditional <func>] [-b|--branch <branch>]
#                        [--pre <func>] [--post <func>]
#                        [-a|--autoload <path>] <bundle>
# <kind>   : zsh,path,fpath,defer,clone,autoload
# <path>   : Relative path from the bundle root
# <branch> : The git branch
# <bundle> : A bundle can be a directory, a zsh script, or a git repo
#

### Generate the Zsh script to load a plugin.
#function antidote-script {
  emulate -L zsh; setopt local_options $_adote_funcopts
  local MATCH MBEGIN MEND; local -a match mbegin mend  # appease 'warn_create_global'
  local REPLY=

  local o_help o_kind o_path o_branch o_cond o_autoload o_pre o_post
  zparseopts $_adote_zparopt_flags -- \
    h=o_help       -help=h            \
    a:=o_autoload  -autoload:=a       \
    b:=o_branch    -branch:=b         \
    k:=o_kind      -kind:=k           \
    p:=o_path      -path:=p           \
                   -pre:=o_pre        \
                   -post:=o_post      \
    c:=o_cond      -conditional:=c    ||
    return 1

  # set defaults
  (( $#o_kind )) || o_kind=(--kind zsh)

  # strip '=' or ':' from beginning of arg values
  local re='^[=:]?(.+)$'
  [[ $o_kind[-1] =~ $re ]] && o_kind[-1]=$match
  [[ $o_autoload[-1] =~ $re ]] && o_autoload[-1]=$match
  [[ $o_path[-1] =~ $re ]] && o_path[-1]=$match
  [[ $o_cond[-1] =~ $re ]] && o_cond[-1]=$match
  [[ $o_branch[-1] =~ $re ]] && o_branch[-1]=$match
  [[ $o_pre[-1] =~ $re ]] && o_pre[-1]=$match
  [[ $o_post[-1] =~ $re ]] && o_post[-1]=$match

  local supported_kind_vals=(autoload clone defer fpath path zsh)
  if (( $#o_kind )) && ! (( $supported_kind_vals[(Ie)$o_kind[-1]] )); then
    print >&2 "antidote: error: unexpected kind value: '$o_kind[-1]'" && return 1
  fi

  local bundle=$1
  if [[ -z "$bundle" ]]; then
    print >&2 "antidote: error: bundle argument expected" && return 1
  fi
  local bundle_name=$(__antidote_bundle_name $bundle)

  # replace ~/ with $HOME/
  if [[ "$bundle" == '~/'* ]]; then
    bundle=$HOME/${bundle#'~/'*}
  fi

  # set the path to the bundle (repo or local)
  local bundle_path
  [[ -e "$bundle" ]] && bundle_path=$bundle || bundle_path=$(__antidote_bundle_dir $bundle)

  # handle cloning repo bundles
  local bundle_type
  bundle_type="$(__antidote_bundle_type $bundle)"
  if [[ "$bundle_type" == (repo|url|sshurl) ]] && [[ ! -e "$bundle_path" ]]; then
    local giturl=$(__antidote_tourl $bundle)
    print >&2 "# antidote cloning $bundle_name..."
    git clone --quiet --depth 1 --recurse-submodules --shallow-submodules $o_branch $giturl $bundle_path
    [[ $? -eq 0 ]] || return 1
  fi

  # if we only needed to clone the bundle, we're done
  [[ "$o_kind[-1]" != "clone" ]] || return

  # add path to bundle
  [[ -n "$o_path[-1]" ]] && bundle_path+="/$o_path[-1]"

  # handle defer pre-reqs first
  local dopts zsh_defer='zsh-defer'
  zstyle -s ":antidote:plugin:${bundle}" defer-options 'dopts'
  [[ -n "$dopts" ]] && zsh_defer="zsh-defer $dopts"

  # generate the script
  local -a script=()

  # add pre-load function
  (( $#o_pre )) && script+=("$o_pre[-1]")

  # handle defers
  local source_cmd="source"
  if [[ "$o_kind[-1]" == "defer" ]]; then
    source_cmd="${zsh_defer} source"
    script+=(
      'if ! (( $+functions[zsh-defer] )); then'
      "$(antidote-script 'romkatv/zsh-defer' | pr -to 2)"
      'fi'
    )
  fi

  # handle autoloading before sourcing
  if (( $#o_autoload )); then
    script+=(
      "fpath+=( ${bundle_path}/${o_autoload[-1]} )"
      "autoload -Uz \$fpath[-1]/*(N.:t)"
    )
  fi

  # generate load script
  bundle_type="$(__antidote_bundle_type $bundle_path)"
  if [[ "$o_kind[-1]" == fpath ]]; then
    # fpath
    script+="fpath+=( $bundle_path )"
  elif [[ "$o_kind[-1]" == path ]]; then
    # path
    script+="export PATH=\"$bundle_path:\$PATH\""
  elif [[ "$o_kind[-1]" == autoload ]]; then
    # autoload
    script+=(
      "fpath+=( $bundle_path )"
      "autoload -Uz \$fpath[-1]/*(N.:t)"
    )
  elif [[ $bundle_type == file ]]; then
    # file
    script+="$source_cmd $bundle_path"
  else
    # directory/default
    local initfile initfiles
    initfiles=(${(@f)$(__antidote_initfiles $bundle_path)})
    # if no init file was found, assume the default
    if [[ $#initfiles -eq 0 ]]; then
      initfiles=($bundle_path/${bundle_path:t}.plugin.zsh)
    fi
    script+="fpath+=( $bundle_path )"
    for initfile in $initfiles; do
      script+="$source_cmd $initfile"
    done
  fi

  # add post-load function
  if (( $#o_post )); then
    if [[ "$o_kind[-1]" == "defer" ]]; then
      script+=("${zsh_defer} $o_post[-1]")
    else
      script+=("$o_post[-1]")
    fi
  fi

  # mark bundle as loaded
  # script+="zstyle ':antidote:plugin:${bundle_name}' loaded yes"

  # wrap conditional
  if [[ -n "$o_cond[-1]" ]]; then
    print "if $o_cond[-1]; then"
    printf "  %s\n" $script
    print "fi"
  else
    printf "%s\n" $script
  fi
#}
