# Copyright (c) 2019 Sebastian Gniazdowski
# License MIT

emulate -RL zsh
setopt extendedglob warncreateglobal typesetsilent noshortloops

[[ "$1" = plugin ]] && \
    local type="$1" user="$2" plugin="$3" id_as="$4" dir="$5" hook="$6" || \
    local type="$1" url="$2" id_as="$3" dir="$4" hook="$5"

local nl=$'\n'

#
# gem'' ice
#

if [[ -n "${ZINIT_ICE[gem]}" ]] {
    local -a gems srcdst tmpsdst
    gems=( "${(s.;.)ZINIT_ICE[gem]}" )

    local gem
    integer add_fbin

    for gem ( $gems ) {
        srcdst=( ${(@s.->.)gem} )
        tmpsdst=( ${(@s.<-.)srcdst[1]} )
        if (( ${#tmpsdst} > 1 )); then
            srcdst=( "${tmpsdst[1]}" "${tmpsdst[2]}" "${srcdst[2]:-${tmpdist[2]#\!}}" )
        else
            srcdst=( "${tmpsdst[1]#\!}" "${tmpsdst[1]}" "${srcdst[2]:-${srcdst[1]#\!}}" )
        fi
        srcdst=( "${srcdst[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" )
        [[ ${srcdst[2]} = \!* ]] && add_fbin=1 || add_fbin=0
        srcdst[2]=${srcdst[2]#\!}

        # Substitute the standard keywords and param''-s
        @zinit-substitute 'srcdst[1]' 'srcdst[2]' 'srcdst[3]'

        if (( add_fbin )); then
            local target_binary="g:$dir/bin/${srcdst[1]}"
            ZINIT_ICE[fbin]+="${ZINIT_ICE[fbin]:+;}$target_binary -> ${srcdst[3]}"
        fi
    }
}

#
# node'' ice
#

if [[ -n "${ZINIT_ICE[node]}" ]] {
    local -a nodes srcdst tmpsdst
    nodes=( "${(s.;.)ZINIT_ICE[node]}" )

    local node
    integer add_fbin

    for node ( $nodes ) {
        srcdst=( ${(@s.->.)node} )
        tmpsdst=( ${(@s.<-.)srcdst[1]} )
        if (( ${#tmpsdst} > 1 )); then
            srcdst=( "${tmpsdst[1]}" "${tmpsdst[2]}" "${srcdst[2]:-${tmpdist[2]#\!}}" )
        else
            srcdst=( "${tmpsdst[1]#\!}" "${tmpsdst[1]}" "${srcdst[2]:-${srcdst[1]#\!}}" )
        fi
        srcdst=( "${srcdst[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" )
        [[ ${srcdst[2]} = \!* ]] && add_fbin=1 || add_fbin=0
        srcdst[2]=${srcdst[2]#\!}

        # Substitute the standard keywords and param''-s
        @zinit-substitute 'srcdst[1]' 'srcdst[2]' 'srcdst[3]'

        if (( add_fbin )); then
            local target_binary="n:$dir/node_modules/.bin/${srcdst[1]}"
            ZINIT_ICE[fbin]+="${ZINIT_ICE[fbin]:+;}$target_binary -> ${srcdst[3]}"
        fi
    }
}

#
# fbin'' ice – also inheriting any exclamation-mark gems
# or node modules
#

if (( ${+ZINIT_ICE[fbin]}${+ZINIT_ICE[fsrc]}${+ZINIT_ICE[ferc]} > 0 )) {
    local -a fbins fsrcs fercs srcdst
    fbins=( ${(s.;.)ZINIT_ICE[fbin]} )
    fsrcs=( ${(s.;.)ZINIT_ICE[fsrc]} )
    fercs=( ${(s.;.)ZINIT_ICE[ferc]} )

    local fbin
    integer run_type=0

    for fbin ( $fbins "" "<sep1>" $fsrcs "" "<sep2>" $fercs "" ) {
        integer set_gem_home=0 set_node_path=0 set_cwd=0 \
                use_all_null=0 use_err_null=0 use_out_null=0

        [[ "$fbin" = "<sep1>" ]] && { run_type=1; continue; }
        [[ "$fbin" = "<sep2>" ]] && { run_type=2; continue; }

        if [[ ( ${+ZINIT_ICE[fbin]} -eq 1 && run_type -eq 0 && -z $fbin && ${#fbins} -eq 0 ) || \
            ( ${+ZINIT_ICE[fsrc]} -eq 1 && run_type -eq 1 && -z $fbin && ${#fsrcs} -eq 0 ) || \
            ( ${+ZINIT_ICE[ferc]} -eq 1 && run_type -eq 2 && -z $fbin && ${#fercs} -eq 0 )
        ]]; then
            if [[ -f $dir/${id_as:t} ]]; then
                fbin="$dir/${id_as:t}"
            elif [[ -n $plugin && -f $dir/$plugin ]]; then
                fbin="$dir/$plugin"
            elif [[ -n $url && -f $dir/${url:t} ]]; then
                fbin="$dir/${url:t}"
            else
                local -a files
                files=( $dir/*(*Non:t) )
                if (( ${#files} )); then
                    fbin="${files[1]}"
                else
                    print -P -- "%F{38}bin-gem-node annex: %F{160}The automatic-empty fbin ice didn't find any executable files for %F{219}$id_as%f"
                    break
                fi
            fi
        elif [[ -z $fbin ]]; then
            continue
        fi

        srcdst=( ${(@s.->.)fbin} )
        srcdst=( "${srcdst[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" )
        [[ ${srcdst[1]} = [gncNEO]#g[gncNEO]#:* ]] && set_gem_home=1
        [[ ${srcdst[1]} = [gncNEO]#n[gncNEO]#:* ]] && set_node_path=1
        [[ ${srcdst[1]} = [gncNEO]#c[gncNEO]#:* ]] && set_cwd=1
        [[ ${srcdst[1]} = [gncNEO]#N[gncNEO]#:* ]] && use_all_null=1
        [[ ${srcdst[1]} = [gncNEO]#E[gncNEO]#:* ]] && use_err_null=1
        [[ ${srcdst[1]} = [gncNEO]#O[gncNEO]#:* ]] && use_out_null=1
        srcdst[1]=${srcdst[1]#[a-zA-Z]#:}
        
        # Substitute the standard keywords and param''-s
        @zinit-substitute 'srcdst[1]' 'srcdst[2]'

        local target_binary="${${(M)srcdst[1]:#/*}:-$dir/${srcdst[1]}}"

        .za-bgn-bin-or-src-function-body "$run_type" \
                       "${srcdst[2]:-${srcdst[1]:t}}" \
                       "$target_binary" "$dir" "$set_gem_home" \
                       "$set_node_path" "$set_cwd" "$use_all_null" \
                       "$use_err_null" "$use_out_null"
        eval "$REPLY"
    }
}

#
# fmod'' ice
#

if [[ -n "${ZINIT_ICE[fmod]}" ]] {
    local -a fmods srcdst
    fmods=( "${(s.;.)ZINIT_ICE[fmod]}" )

    local fmod

    for fmod ( $fmods ) {
        integer set_gem_home=0 set_node_path=0 set_cwd=0 \
                use_all_null=0 use_err_null=0 use_out_null=0

        srcdst=( ${(@s.->.)fmod} )
        srcdst=( "${srcdst[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" )
        [[ ${srcdst[1]} = [gncNEO]#g[gncNEO]#:* ]] && set_gem_home=1
        [[ ${srcdst[1]} = [gncNEO]#n[gncNEO]#:* ]] && set_node_path=1
        [[ ${srcdst[1]} = [gncNEO]#c[gncNEO]#:* ]] && set_cwd=1
        [[ ${srcdst[1]} = [gncNEO]#N[gncNEO]#:* ]] && use_all_null=1
        [[ ${srcdst[1]} = [gncNEO]#E[gncNEO]#:* ]] && use_err_null=1
        [[ ${srcdst[1]} = [gncNEO]#O[gncNEO]#:* ]] && use_out_null=1
        srcdst[1]=${srcdst[1]#[a-zA-Z]#:}
        
        # Substitute the standard keywords and param''-s
        @zinit-substitute 'srcdst[1]' 'srcdst[2]'

        local target_function="${srcdst[1]}"

        .za-bgn-mod-function-body "${srcdst[2]:-${srcdst[1]}}" \
                       "$target_function" "$dir" "$set_gem_home" \
                       "$set_node_path" "$set_cwd" "$use_all_null" \
                       "$use_err_null" "$use_out_null"
        eval "$REPLY"
    }
}

# vim:ft=zsh:sw=4:sts=4:et
