# shellcheck shell=dash

# ___x_cmd_pkg_sphere_populate --sphere X --osarch <osarch> <pkg name> <version>

___x_cmd_pkg_sphere_populate(){
    local op="$1";
    case "$op" in
        done|run)   shift; ___x_cmd_pkg_sphere_populate_"$op" "$@" ;;
        get_exist_dir_|get_exist_dir|get_link_source_dir_|get_link_source_dir|list_link_source_dir)
                    shift; ___x_cmd_pkg_sphere_populate___"$op" "$@" ;;
        *)          N=pkg M="sphere gc not such option '$op'" log:ret:64
    esac
}

___x_cmd_pkg_sphere_populate_done(){
    pkg:sphere:parse:args
    local x_treename=; ___x_cmd_pkg_treename_ "$name" "$version" "$osarch" || return $?
    local done_file="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/$x_treename/$name/$version/.x-cmd/donefile"
    [ -f "$done_file" ]
}

___x_cmd_pkg_sphere_populate_run(){
    pkg:sphere:parse:args

    local x_treename=; ___x_cmd_pkg_treename_ "$name" "$version" "$osarch" || return $?
    local tgt="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/$x_treename/$name/$version"
    local done_file="$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/$x_treename/$name/$version/.x-cmd/donefile"

    ! [ -f "$done_file" ] || return 0

    pkg:info "Trying populate ==> '$name $version'"

    local download_file_ext=; local unpack=;
    ___x_cmd_pkg___attr "$name" "$version" "$osarch" "url.${___X_CMD_WEBSRC_REGION:-internet},download_file_ext,unpack" || return $?
    eval "local url=\$url_${___X_CMD_WEBSRC_REGION:-internet}"
    [ -z "$url" ] || {
        ___x_cmd_pkg_sphere_populate___unzip "$name" "$version" "$osarch" "$tgt" "$download_file_ext" "$unpack" || {
            pkg:error "Unzip $name $version $osarch failed"
            ___x_cmd rmrf "$tgt"
            return 1
        }
    }

    local script_path
    if ! script_path="$( ___x_cmd_pkg___get_script_path "$name" "$version" "$osarch" populate )"; then
        pkg:error "Not found $name $version $osarch populate script file"
        ___x_cmd rmrf "$tgt"
        return 1
    fi

    if [ -f "$script_path" ]; then
        pkg:info "Running $script_path"
        pkg:debug --name "$name" --version "$version" --osarch "$osarch" --script_path "$script_path"

        local ___X_CMD_PKG___META_NAME="$name"
        local ___X_CMD_PKG___META_VERSION="$version"
        local ___X_CMD_PKG___META_OS="${osarch%%/*}"
        local ___X_CMD_PKG___META_ARCH="${osarch#*/}"
        local ___X_CMD_PKG___META_TGT="$tgt"
        local ___X_CMD_PKG___META_SPHERE_NAME="$sphere_name"
        pkg:debug \
            --___X_CMD_PKG___META_NAME "$___X_CMD_PKG___META_NAME"          \
            --___X_CMD_PKG___META_VERSION "$___X_CMD_PKG___META_VERSION"    \
            --___X_CMD_PKG___META_OS "$___X_CMD_PKG___META_OS"              \
            --___X_CMD_PKG___META_ARCH "$___X_CMD_PKG___META_ARCH"          \
            --___X_CMD_PKG___META_TGT "$___X_CMD_PKG___META_TGT"            \
            --___X_CMD_PKG___META_SPHERE_NAME "$___X_CMD_PKG___META_SPHERE_NAME"
        {
            (
                trap 'printf "\r\n"; pkg:error "populate interrupted script"; return 130' INT
                . "$script_path"
            ) || {
                pkg:error "Source $script_path failed"
                ___x_cmd rmrf "$tgt"
                return 1
            }
        }
    fi

    ___x_cmd_pkg_sphere_populate___chmod "$name" "$version" "$osarch" "$tgt" || return $?

    if ___x_cmd_pkg___is_support_use "$name"; then
        ___x_cmd_pkg_sphere snap gen_execfp \
            --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" \
            --osarch "$osarch" "$name" "$version" || return $?
    fi

    pkg:debug "Add $name $version populate done file"
    ___x_cmd touch "$done_file"

    pkg:info "$name $version install successfully"
}

# This is default
___x_cmd_pkg_sphere_populate___unzip(){
    local name="$1"; local version="$2"; local osarch="$3"; local tgt="$4";
    local download_file_ext="$5"; local unpack="$6";
    shift 6

    local tree=;    local ball=
    ___x_cmd_pkg___attr "$name" "$version" "$osarch" "tree" || return $?

    [ -n "$unpack" ] || {
        pkg:debug "Skip unzip"
        return 0
    }

    if [ "$unpack" = "none" ] && [ -z "$download_file_ext" ]; then
        ball="$___X_CMD_PKG_DOWNLOAD_PATH/$name/$name.${tree}"
    else
        ball="$___X_CMD_PKG_DOWNLOAD_PATH/$name/${version}.${tree}.${download_file_ext}"
    fi

    [ -f "$ball" ] || N=pkg M="Not found zip package => $name $version" log:ret:1

    # TODO: Optimize unzip
    if [ "$unpack" = "folder" ]; then
        pkg:info  --ball "$ball" --target_dir "$tgt" "Unpacking"
        local unpack_dir="$___X_CMD_PKG_DOWNLOAD_PATH/$name/$version"
        ___X_CMD_ZUZ_QUIET=1 ___x_cmd uz "$ball" "$unpack_dir" || N=pkg M="Fail to unzip $ball" log:ret:1
        pkg:info "Unpacking completed"
        local x_=; ___x_cmd fsiter --dir01_ "$unpack_dir" || return $?
        pkg:debug --target_dir "$tgt" "Moving $unpack_dir/$x_"
        [ -d "$tgt" ] || ___x_cmd rmrf "$tgt"
        ___x_cmd mv "$unpack_dir/$x_" "$tgt" || return $?
        ___x_cmd rmrf "$unpack_dir"
    elif [ "$unpack" = "none" ]; then
        pkg:info  --ball "$ball" --target_dir "$tgt" "Copying"
        [ -d "$tgt" ] || ___x_cmd rmrf "$tgt"; ___x_cmd ensurefp "$tgt"
        ___x_cmd mkdirp "$tgt"
        ___x_cmd cp -f "$ball" "$tgt/"
    elif [ "$unpack" = "file" ]; then
        pkg:info  --ball "$ball" --target_dir "$tgt" "Unpacking"
        [ -d "$tgt" ] || ___x_cmd rmrf "$tgt"; ___x_cmd mkdirp "$tgt"
        ___X_CMD_ZUZ_QUIET=1 ___x_cmd uz "$ball" "$tgt"  || N=pkg M="Fail to unzip $ball" log:ret:1
        pkg:info "Unpacking completed"
    elif [ "$unpack" = "stationary" ]; then
        return 0
    else
        pkg:error "Yml of $name $version lacks of unpack key"
        return 1
    fi
}

___x_cmd_pkg_sphere_populate___chmod(){
    local name="$1"; local version="$2"; local osarch="$3"; local tgt="$4"
    shift 4
    local bin_path; local xbin_name;
    while ___x_cmd_readr xbin_name; do
        [ -n "$xbin_name" ] || continue
        [ "${xbin_name##*:}" = "$name" ] || continue
        xbin_name="${xbin_name#*:}"
        xbin_name="${xbin_name%:*}"
        bin_path="$(___x_cmd_pkg_sphere_xbin path "$xbin_name" "$version" "$osarch")"
        if  [ -f "$bin_path" ]; then
            ___x_cmd_cmds chmod +x "$bin_path" || {
                pkg:error "Cannot use chmod on $bin_path"
                ___x_cmd rmrf "$tgt"
                return 1
            }
        fi
    done < "$___X_CMD_PKG_METADATA_PATH/binmod.txt"
}

___x_cmd_pkg_sphere_populate___get_exist_dir_(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-"X"}"
    local name="$1"
    local version="$2"
    local i; for i in "$___X_CMD_PKG_ROOT_SPHERE/$sphere_name/"*"/$name/$version"; do
        [ ! -d "$i" ] || break
    done 2>/dev/null
    x_="$i"
    [ -d "$x_" ]
}
___x_cmd_pkg_sphere_populate___get_exist_dir(){
    local x_=""
    ___x_cmd_pkg_sphere_populate___get_exist_dir_ "$@" || return $?
    printf "%s\n" "$x_"
}

___x_cmd_pkg_sphere_populate___get_link_source_dir_(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-X}"
    local name="$1";    [ -n "$name" ] || N=pkg M="Provide a package name" log:ret:1
    local version="$2"
    if [ -n "$version" ]; then
        ___x_cmd_pkg_sphere_link exist \
            --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" "$name" "$version" || {
            pkg:debug "Unlinked [name=$name] [version=$version], not found source directory for link"
            return 1
        }
    else
        x_=; ___x_cmd_pkg_sphere_link get_version_ \
            --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" "$name" || {
            pkg:debug "Not found source directory for link [name=$name]"
            return 1
        }
        version="$x_"
    fi
    x_=""
    ___x_cmd_pkg_sphere_populate___get_exist_dir_ \
        --sphere "$sphere_name" --sphereroot "$___X_CMD_PKG_ROOT_SPHERE" "$name" "$version"
}

___x_cmd_pkg_sphere_populate___get_link_source_dir(){
    local x_=""
    ___x_cmd_pkg_sphere_populate___get_link_source_dir_ "$@" || return $?
    printf "%s\n" "$x_"
}

___x_cmd_pkg_sphere_populate___list_link_source_dir(){
    pkg:sphere:parse:option
    sphere_name="${sphere_name:-X}"
    local name=; local x_=
    while [ "$#" -gt 0 ]; do
        name="$1"; shift
        x_=; ___x_cmd_pkg_sphere_populate___get_link_source_dir_ "$name" || continue
        printf "%s,%s\n" "$name" "$x_"
    done
}
