# shellcheck shell=dash

___x_cmd_apt___xmirror(){
    local ___X_CMD_APT_MIRROR_SOURCES=
    local ___X_CMD_OS_RELEASE=
    ___x_cmd_apt___xmirror___ensure || return $?

    [ "$#" -gt 0 ] || { ___x_cmd_apt___xmirror___app ; return ; }

    local op="$1"; shift
    case "$op" in
        -h|--help)
                ___x_cmd help -m apt mirror                  "$@" ;;
        ls|replace|current|rollback)
                ___x_cmd_apt___xmirror_"${op}"               "$@" ;;
        set)    ___x_cmd_apt___xmirror_replace               "$@" ;;
        unset)  ___x_cmd_apt___xmirror_rollback              "$@" ;;
        *)      N=apt M="subcommand not found."    log:ret:1      ;;
    esac
}

___x_cmd_apt___xmirror___ensure(){
    ___x_cmd_hascmd apt || N=apt M="[command=apt] not found." log:ret:1

    ___X_CMD_OS_RELEASE="$(___x_cmd os release)"
    case "$___X_CMD_OS_RELEASE" in
        *Ubuntu*|*ubuntu*)
            ___X_CMD_OS_RELEASE="ubuntu"
            ___X_CMD_APT_MIRROR_SOURCES="/etc/apt/sources.list"
            ;;
        *Kali*|*kali*)
            ___X_CMD_OS_RELEASE="kali"
            ___X_CMD_APT_MIRROR_SOURCES="/etc/apt/sources.list"
            ;;
        *Debian*|*debian*)
            case "$(uname -a)" in
                # TODO: test raspberrypi
                *Raspberrypi*|*raspberrypi*)
                    ___X_CMD_OS_RELEASE="raspberrypi"
                    ___X_CMD_APT_MIRROR_SOURCES="/etc/apt/sources.list.d/raspi.list"
                    ;;
                *)
                    ___X_CMD_OS_RELEASE="debian"
                    ___X_CMD_APT_MIRROR_SOURCES="/etc/apt/sources.list.d/debian.sources"
                    ;;
            esac
            ;;
        *)
            N=apt M="Unsupported system: $___X_CMD_OS_RELEASE" log:ret:1
            ;;
    esac
    [ -f "$___X_CMD_APT_MIRROR_SOURCES" ] || ___X_CMD_APT_MIRROR_SOURCES="/etc/apt/sources.list"
}

___x_cmd_apt___xmirror___app(){
    local _SELECT
    ___x_cmd ui select "_SELECT" \
        "Methods:" \
            "Set apt mirror (default is ali)" \
            "Get current apt mirror" \
            "List all the apt mirror candidates" \
            "Rollback the apt mirror to the original official"

    case "$_SELECT" in
        1)  ___x_cmd_apt___xmirror replace       ;;
        2)  ___x_cmd_apt___xmirror current       ;;
        3)  ___x_cmd_apt___xmirror ls            ;;
        4)  ___x_cmd_apt___xmirror rollback      ;;
        *)  apt:info "Canceled" ;        return 1 ;;
    esac
}

___x_cmd_apt___xmirror_ls(){
    printf "%s\n" \
        "Code          Url                                  Name"                  \
        "ali           mirrors.aliyun.com                   阿里云镜像"              \
        "tuna          mirrors.tuna.tsinghua.edu.cn         清华大学镜像"            \
        "bfsu          mirrors.bfsu.edu.cn                  北京外国语大学镜像"       \
        "ustc          mirrors.ustc.edu.cn                  中国科学技术大学镜像"     \
        "tencent       mirrors.tencent.com                  腾讯云镜像"
}

___x_cmd_apt___xmirror_advise_ls(){
    ___x_cmd_apt___xmirror_ls | ___x_cmd_cmds_awk 'NR >1 { print $1 }'
}

___x_cmd_apt___xmirror_current(){
    ___x_cmd_cmds_cat "$___X_CMD_APT_MIRROR_SOURCES"
}

___x_cmd_apt___xmirror___url(){
    ___x_cmd_apt___xmirror_ls | \
        ___x_cmd_mirror___util_get_url_by_name "$1"
}

# TODO: Just replace the original text, maybe not the best way.
# shellcheck disable=SC2120
___x_cmd_apt___xmirror_replace() {
    [ "$#" -gt 0 ] ||   set -- ali
    case "$1" in
        -h|--help) ___x_cmd help -m mirror apt replace "$@";    return ;;
    esac

    ___x_cmd_apt___xmirror_save || N=apt M="Save apt original sources list failed." log:ret:1

    # TODO: Some problem in ubuntu 12.04
    local url
    url="$(___x_cmd_apt___xmirror___url "${1}")" || return $?
    if [ -z "$url" ]; then
        apt:error "Invalid mirror name: $1"
        return 1
    fi
    apt:info "Setting apt mirror $url"

    # ___x_cmd_proxy___util_backup "$___X_CMD_APT_MIRROR_SOURCES" apt

    ___x_cmd os name_
    local repo_arch="$___X_CMD_OS_RELEASE"
    [ "$___X_CMD_OS_RELEASE" != "ubuntu" ] || {
        ___x_cmd os arch_
        [ "$___X_CMD_OS_ARCH_" = "x64" ] || repo_arch="$___X_CMD_OS_RELEASE-ports"
    }

    local tmp
    tmp="$(___x_cmd_cmds_cat "$___X_CMD_APT_MIRROR_SOURCES")"

    # If there is no root permission, use sudo
    if [ "$(id -u)" -ne 0 ]; then
        apt:warn "using sudo"
        printf "%s" "$tmp" | \
            ___x_cmd_cmds awk '!/^#/ && !/security/ { gsub(/(:\/\/[^ ]*)/, "://'"$url"'/'"$repo_arch"'"); } { print }' \
        | sudo tee "$___X_CMD_APT_MIRROR_SOURCES" > /dev/null
        ___x_cmd sudo apt update
    else
        printf "%s" "$tmp" | \
            ___x_cmd_cmds awk '!/^#/ && !/security/ { gsub(/(:\/\/[^ ]*)/, "://'"$url"'/'"$repo_arch"'"); } { print }' \
        > "$___X_CMD_APT_MIRROR_SOURCES"
        ___x_cmd_cmds apt update
    fi
}

# Rollback from the last backup file.
# Get the last backup file from the backup directory.
# shellcheck disable=SC2120

___x_cmd_apt___xmirror_save(){
    ___x_cmd_mirror___util_save "$___X_CMD_APT_MIRROR_SOURCES" "apt"
}

___x_cmd_apt___xmirror_rollback(){
    ___x_cmd_mirror___util_rollback_original "$___X_CMD_APT_MIRROR_SOURCES" "apt" || return $?
    ___x_cmd rmrf "$___X_CMD_ROOT_DATA/mirror/apt"

    if [ "$(id -u)" -ne 0 ]; then
        ___x_cmd sudo apt update
    else
        ___x_cmd_cmds apt update
    fi
}

