# shellcheck    shell=sh            disable=SC3043,2155      # xrc

# Section: xbin

___x_cmd_pkg_sphere_xbin(){
    x:trace pkg/xbin
    local X_help_cmd='___x_cmd help -m pkg xbin';   help:arg-null:parse

    # TODO: Need to be removed in the future
    ___x_cmd_pkg_update___check || return $?
    local op="$1"
    case "$op" in
        init|path|remove_cache|get_binmod_name_|exec)
            shift; ___x_cmd_pkg_sphere_xbin_"$op" "$@" ;;
        *)          return 1 ;;
    esac
}

# <bin-name> <version>
___x_cmd_pkg_sphere_xbin_path(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-"X"}"

    local bin_mod_name="${1}";  [ -n "$bin_mod_name" ] || M='Provide bin mod name' N=pkg log:ret:1

    local x_=; ___x_cmd_pkg_sphere_xbin_get_binmod_name_ "$bin_mod_name" || return 1
    local pkg_name="$x_"
    local version="$2"; [ -n "$version" ] || {
        x_=; ___x_cmd_pkg_default_version_ "$pkg_name" "$osarch" || N=pkg M="Not found $pkg_name version" log:ret:1;
        version="$x_";
    }

    pkg:debug --bin_mod_name "$bin_mod_name" --package "$pkg_name" --version "$version" xbin_path

    local datalist; datalist="$( ___x_cmd_pkg___all_info --non-version "$pkg_name" "$version" "$osarch" )" || return $?
    local bin_rpath; bin_rpath="$(
    printf "%s\n\n" "$datalist" | ___x_cmd_cmds_awk \
        -v BIN_MOD_NAME="$bin_mod_name" \
        -f "$___X_CMD_ROOT_MOD/awk/lib/core.awk"        \
        -f "$___X_CMD_ROOT_MOD/awk/lib/j/json.awk"      \
        -f "$___X_CMD_ROOT_MOD/awk/lib/j/jqparse.awk"   \
        -f "$___X_CMD_ROOT_MOD/pkg/lib/awk/util.awk"    \
        -f "$___X_CMD_ROOT_MOD/pkg/lib/awk/pkg._.awk"   \
        -f "$___X_CMD_ROOT_MOD/pkg/lib/awk/pkg.xbin.awk"
    )"
    [ -n "$bin_rpath" ] || N=pkg M="Not found bin path of $bin_mod_name" log:ret:1

    local x_treename=; ___x_cmd_pkg_treename_ "$pkg_name" "$version" "$osarch" || return $?
    local tgt="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/$x_treename/$pkg_name/$version"
    pkg:debug "INSTALL_PATH => $tgt"
    printf "%s\n" "$tgt/$bin_rpath"
}

___x_cmd_pkg_sphere_xbin_exec(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-"X"}"

    # local pkg_name=
    # local pkg_version=
    # local xbin_dir=
    # while [ "$#" -gt 0 ]; do
    #     case "$1" in
    #         -s|--spec)  pkg_name="$2";      shift 2 ;;
    #         --version)  pkg_version="$2";   shift 2 ;;
    #         --bin_dir)  xbin_dir="$2";      shift 2 ;;
    #         *)          break ;;
    #     esac
    # done

    local bin_mod_name="${1}";  [ -n "$bin_mod_name" ] || M='Provide bin mod name' N=pkg log:ret:1
    local ___X_CMD_STR___DASH2UNDERLINE=; ___x_cmd_str___dash2underline "$bin_mod_name"
    local bin_mod_func_name="___x_cmd_pkg_sphere_xbin_exec___function_${___X_CMD_STR___DASH2UNDERLINE}"

    ___x_cmd hascmd "$bin_mod_func_name" || {
        ___x_cmd_pkg_sphere_xbin_init \
            --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE"    \
            --osarch "$osarch" "$bin_mod_name" "$bin_mod_func_name" || return $?
    }

    shift
    "$bin_mod_func_name" "$@"
}

# <bin-name> <function-name> <binpath-env-name>
# x pkg xbin init tmux ___x_cmd___tmux_origin ___X_CMD_TMUX_BIN
___x_cmd_pkg_sphere_xbin_init(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-"X"}"

    local bin_mod_name="${1}";  [ -n "$bin_mod_name" ] || M='Provide bin mod name' N=pkg log:ret:1
    local bin_mod_path_name="${3}"

    local ___X_CMD_STR___DASH2UNDERLINE=; ___x_cmd_str___dash2underline "$bin_mod_name"
    local bin_mod_func_name="${2:-"___x_cmd_${___X_CMD_STR___DASH2UNDERLINE}"}"
    local xbin_cachepath="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/.x-cmd/xbin/$osarch/$___X_CMD_STR___DASH2UNDERLINE/$bin_mod_func_name";

    # TODO: Need to be removed in the future
    ___x_cmd_pkg_update___check # ensure existense of "$___X_CMD_PKG_FP_UPDATED_DONE"
    ___x_cmd depend run "$xbin_cachepath" -- "$___X_CMD_PKG_FP_UPDATED_DONE" -- ___x_cmd_pkg_sphere_xbin_init___cache
    [ -f "$xbin_cachepath" ] || return $?
    pkg:debug "xbin cache path => $xbin_cachepath"
    . "$xbin_cachepath"
}

___x_cmd_pkg_sphere_xbin_init___cache(){
    local x_=; ___x_cmd_pkg_sphere_xbin_get_binmod_name_ "$bin_mod_name" || return 1
    local pkg_name="$x_"
    x_=; ___x_cmd_pkg_default_version_ "$pkg_name" "$osarch" || N=pkg M="Not found $pkg_name version" log:ret:1;
    local version="$x_";

    local bin_path
    bin_path="$(___x_cmd_pkg_sphere_xbin_path --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" --osarch "$osarch" "$bin_mod_name" "$version")"
    pkg:debug --bin_mod_name "$bin_mod_name" --package "$pkg_name" --version "$version" --binpath "$bin_path" xbin_init

    [ -f "$bin_path" ] || ___x_cmd_pkg_sphere_add --prebuild --protection use --reason "use,xbin-init" --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" --osarch "$osarch" "$pkg_name" "$version" || return $?
    [ -f "$bin_path" ] || N=pkg M="Not found $pkg_name $version bin path" log:ret:1
    ___x_cmd_cmds chmod +x "$bin_path" || N=pkg M="chmod $bin_path - Operation not permitted" log:ret:1

    # TODO: source shim_bin path
    local bin_code="
$bin_mod_func_name(){
    ${bin_path} \"\$@\"
}
"

#     local bin_code="
# ${bin_mod_func_name}___binpath=\"\$bin_path\"
# $bin_mod_func_name(){
#     ___x_cmd_pkg_sphere_xbin_ensurefp_and_exec ${sphere_name} ${osarch} ${pkg_name} ${version} \"\$${bin_mod_func_name}___binpath\" \"\$@\"
# }
#     "
    [ -z "$bin_mod_path_name" ] || {
        bin_code="$bin_mod_path_name=\"$bin_path\"
${bin_code}"
    }

    ___x_cmd ensurefp "$xbin_cachepath"
    printf "%s\n" "$bin_code" > "$xbin_cachepath"
}

___x_cmd_pkg_sphere_xbin_ensurefp_and_exec(){
    local sphere_name="$1"
    local osarch="$2"
    local name="$3";
    local version="$4";
    local bin_fp="$5";

    [ -f "$bin_fp" ] || ___x_cmd pkg sphere add --prebuild  \
        --protection use --reason "use,xbin-init"           \
        --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" \
        --osarch "$osarch" "$name" "$version" || return $?

    shift 5
    "${bin_fp}" "$@"
}
# EndSection

# Section: xbin remove
# <pkg-name> <version>
___x_cmd_pkg_sphere_xbin_remove_cache(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-"X"}"

    local pkg_name="${1}";  [ -n "$pkg_name" ]  || N=pkg    M='Provide a pkg name'              log:ret:1
    local version="$2";     [ -n "$version" ]   || N=pkg    M="Not found $pkg_name version"     log:ret:1

    local x_=; ___x_cmd_pkg_default_version_ "$pkg_name" "$osarch" || return $?
    local default_version="$x_"
    [ "$default_version" = "$version" ] || return 0

    local xbin_cachedir="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/.x-cmd/xbin/$osarch";
    local xbin_name=; local ___X_CMD_STR___DASH2UNDERLINE=;

    {
        local line=;
        local fp=
        while ___x_cmd_readr line; do
            xbin_name="${line%":${pkg_name}"}"
            [ "${xbin_name}" != "${line}" ] || continue

            ___X_CMD_STR___DASH2UNDERLINE=;
            ___x_cmd_str___dash2underline "${xbin_name#:}"
            fp="$xbin_cachedir/$___X_CMD_STR___DASH2UNDERLINE"

            pkg:debug "Removing xbin cache => $fp"
            [ ! -d "$fp" ] || ___x_cmd rmrf "$fp"
        done
    } <"$___X_CMD_PKG_METADATA_PATH/binmod.txt"
}
# EndSection

# Section: xbin get binmod name
___x_cmd_pkg_sphere_xbin_get_binmod_name_(){
    local bin_mod_name="${1}"
    [ -n "$bin_mod_name" ] || M='Provide bin mod name' N=pkg log:ret:1

    # TODO: Need to be removed in the future
    ___x_cmd_pkg_update___check || return $?
    if [ -z "$___X_CMD_PKG_BINMOD_MAP" ]; then
        ___X_CMD_PKG_BINMOD_MAP="$(___x_cmd_cmds_cat "$___X_CMD_PKG_METADATA_PATH/binmod.txt")"
    fi

    local pkg_name="${___X_CMD_PKG_BINMOD_MAP#*:"$bin_mod_name":}"
    if [ "$pkg_name" = "${___X_CMD_PKG_BINMOD_MAP}" ]; then
        if [ -z "$___X_CMD_PKG_SPHERE_XBIN_IS_SILENT" ]; then
            pkg:warn "Not found pkg - ${bin_mod_name}"
        else
            pkg:debug "Not found pkg - ${bin_mod_name}"
        fi
        return 1
    fi

    pkg_name="${pkg_name%%
*}"

    x_="$pkg_name"
}
# EndSection
