# shellcheck    shell=sh    disable=SC3043  # xrc

# Section: uname
___x_cmd_os_lsuname(){
    printf "%s" "linux
darwin
sunos
freebsd
openbsd
aix
cygwin
msys
mingw
"
}

___x_cmd_os_uname_(){
    if [ -z "$___X_CMD_OS_UNAME_" ]; then
        case "$(command uname -a)" in
            Linux\ *)                   ___X_CMD_OS_UNAME_=linux ;;
            Darwin\ *)                  ___X_CMD_OS_UNAME_=darwin ;;
            SunOS\ *)                   ___X_CMD_OS_UNAME_=sunos ;;
            FreeBSD\ *)                 ___X_CMD_OS_UNAME_=freebsd ;;
            OpenBSD\ *)                 ___X_CMD_OS_UNAME_=openbsd ;;         # TODO: Netbsd?
            AIX\ *)                     ___X_CMD_OS_UNAME_=aix ;;
            CYGWIN* | MSYS* | MINGW*)   ___X_CMD_OS_UNAME_=win ;;
        esac
    fi
    x_="$___X_CMD_OS_UNAME_"
}

___x_cmd_os_uname() {
    local x_=; ___x_cmd_os_uname_ || return $?
    if [ "$#" -eq 0 ]; then
        printf "%s\n" "$___X_CMD_OS_UNAME_"
    else
        x case "$___X_CMD_OS_UNAME_" "$@"
    fi
}

# EndSection


# Section: name
___x_cmd_os_lsname(){
    printf "%s" "linux
darwin
sunos
freebsd
openbsd
aix
win"
}

___X_CMD_OS_NAME_FP="$___X_CMD_ROOT_DATA/os/name"
___x_cmd_os_name_(){
    x_=""

    if [ -n "$___X_CMD_OS_NAME_" ]; then
        x_="$___X_CMD_OS_NAME_"
        return
    fi

    if [ -f "$___X_CMD_OS_NAME_FP" ]; then
        read -r x_<"$___X_CMD_OS_NAME_FP"
    fi

    if [ -z "$x_" ]; then
        ___x_cmd_os_getname_ || return $?
        ___x_cmd fprintf    "$___X_CMD_OS_NAME_FP"   "%s\n" "$x_"
    fi

    ___X_CMD_OS_NAME_="$x_"
}

___x_cmd_os_getname_(){
    case "$(command uname -a)" in
        Linux\ *)                   x_=linux ;;
        Darwin\ *)                  x_=darwin ;;
        SunOS\ *)                   x_=sunos ;;
        FreeBSD\ *)                 x_=freebsd ;;
        OpenBSD\ *)                 x_=openbsd ;;         # TODO: Netbsd?
        AIX\ *)                     x_=aix ;;
        CYGWIN* | MSYS* | MINGW*|Windows*)
                                    x_=win ;;
        *)                          return 1
    esac
}

___x_cmd_os_is(){
    local x_=;
    case "$1" in
        wsl)        ___x_cmd_os_is_wsl ;;
        termux)     ___x_cmd_is_termux ;;
        gitbash)    ___x_cmd_os_is_gitbash ;;
        *)          ___x_cmd_os_name_
                    [ "$x_" = "$1" ]
                    ;;
    esac
}

___x_cmd_os_is_wsl(){
    [ -n "$WSL_INTEROP" ]
}

___x_cmd_os_is_gitbash(){
    [ -n "$MSYSTEM" ]
}


___x_cmd_os_name() {
    # Notcie: ___X_CMD_OS_NAME_ is remained in this environment as cache. Don't make it local.

    # x_:run ___x_cmd_os_name_
    # TODO: Add case.
    #  x os name --ret abc,cde,efg
    # x:ret <var1> <var2> <var3>
    # ret=a,b,c x os name
    # x_=cde x os name

    local x_=""; ___x_cmd_os_name_ || return $?
    if [ "$#" -eq 0 ]; then
        printf "%s\n" "$x_"
    else
        ___x_cmd case "$x_" "$@"
    fi
}

# EndSection


# Section: arch
___x_cmd_os_lsarch(){
    printf "%s" "linux
x64
x64
arm64
armv7l"
}


___X_CMD_OS_ARCH_FP="$___X_CMD_ROOT_DATA/os/arch"

___x_cmd_os_arch_() {
    x_=""

    if [ -n "$___X_CMD_OS_ARCH_" ]; then
        x_="$___X_CMD_OS_ARCH_"
        return 0
    fi

    if [ -f "$___X_CMD_OS_ARCH_FP" ]; then
        read -r x_<"$___X_CMD_OS_ARCH_FP"
    fi

    if [ -z "$x_" ]; then
        ___x_cmd_os_getarch_  || return $?
        ___x_cmd fprintf    "$___X_CMD_OS_ARCH_FP"   "%s\n" "$x_"
    fi

    ___X_CMD_OS_ARCH_="$x_"
}

___x_cmd_os_arch(){
    local x_=""; ___x_cmd_os_arch_ "$@" || return $?

    if [ "$#" -eq 0 ]; then
        printf "%s\n" "$x_"
    else
        ___x_cmd case "$x_" "$@"
    fi
}

___x_cmd_os_getarch_(){
        local HOST_ARCH=""

        x_=""
        ___x_cmd_os_name_
        local osname="$x_"

        if [ "${osname}" = "sunos" ]; then
            # first try to use pkgsrc to guess the most appropriate arch.
            if HOST_ARCH=$(pkg_info -Q MACHINE_ARCH pkg_install 2>/dev/null); then
                HOST_ARCH=$(echo "${HOST_ARCH}" | command tail -1)
            else
                # If it's not available, use isainfo to get the instruction set supported by the kernel.
                HOST_ARCH=$(isainfo -n)
            fi
        elif [ "${osname}" = "aix" ]; then
            HOST_ARCH=ppc64
        else
            HOST_ARCH="$(command uname -m)"
        fi

        x_=""
        case "${HOST_ARCH}" in
            x86_64 | amd64)     x_="x64" ;;
            i*86)               x_="x86" ;;
            aarch64)            x_="arm64" ;;
            *)                  x_="${HOST_ARCH}" ;;     # TODO: Consider 32bit arm? For router or raspberry pi 3?
        esac

        # If running a 64bit ARM kernel but a 32bit ARM userland, change ARCH to 32bit ARM (armv7l)
        if [ "$osname" = "Linux" ] && [ "${x_}" = arm64 ]; then
            local L
            L=$(___x_cmd_cmds_ls -dl /sbin/init 2>/dev/null) #                                         if /sbin/init is 32bit executable
            if [ "$(od -An -t x1 -j 4 -N 1 "${L#*-> }")" = ' 01' ]; then
                x_=armv7l
            fi
        fi
}

# EndSection
