# shellcheck shell=bash disable=SC1090,2317

___X_CMD_REPLHOOK=
___x_cmd_replhook_enable(){
    # TODO: What if I want to reload again ?
    [ -z "$___X_CMD_REPLHOOK" ] || return "$___X_CMD_REPLHOOK"

    if ___x_cmd hascmd precmd && ___x_cmd hascmd preexec; then
        ___X_CMD_REPLHOOK=1
        return 1
    fi

    case "$___X_CMD_SHELL" in
        bash)
            ___x_cmd_replhook___load_bash_preexec || {
                x:error "Failed to load bash-preexec"
                ___X_CMD_REPLHOOK=1
                return 1
            }

            xrc:mod:lib x-cmd   replhook/preexec.bash
            ___X_CMD_REPLHOOK=0
            ;;
        zsh)
            ___X_CMD_REPLHOOK=0
            xrc:mod:lib x-cmd   replhook/preexec.zsh
            ;;
        *)
            x:debug "Unsupported $___X_CMD_SHELL"
            ___X_CMD_REPLHOOK=1
            ;;
    esac

    return "$___X_CMD_REPLHOOK"
}

___x_cmd_replhook___load_bash_preexec(){
    # Notice: "x pkg xbin path bash-preexec" will result in efficiency loss.
    local _file=
    local _cache_fp="$___X_CMD_ROOT_TMP/replhook/filepath/bash-preexec"
    if [ -f "$_cache_fp" ]; then
        read -r _file < "$_cache_fp"
    fi

    if [ -z "$_file" ] || [ ! -f "$_file" ]; then
        xrc pkg

        ___x_cmd_pkg___is_support bash-preexec || {
            x:warn "Not found candidate[bash-preexec]${x_replhook_feature:+", for the ${x_replhook_feature}"}, please use \`x pkg update\`"
            return 1
        }

        ___x_cmd_pkg_osarch_ || return 1
        local x_treename=; ___x_cmd_pkg_treename_get_form_tree_ "$___X_CMD_PKG_OSARCH" || return 1
        _file="$___X_CMD_PKG_ROOT_SPHERE/X/$x_treename/bash-preexec/v0.5.0/bash-preexec.sh"
        [ -f "$_file" ] || ___x_cmd_pkg_sphere add --prebuild --protection use --sphere X bash-preexec "v0.5.0" "$___X_CMD_PKG_OSARCH" || return 1
        ___x_cmd ensurefp "$_cache_fp"
        printf "%s\n" "$_file" > "$_cache_fp"
    fi

    [ -f "$_file" ] || N=x M="No such [file=$_file]" log:ret:1
    . "$_file"
}

___x_cmd_replhook_trapint_init(){
    ___X_CMD_REPLHOOK_PREEXEC_DONE=1
    ___x_cmd_replhook_debug_inside_trapc(){ return 1; };
    ___x_cmd_replhook_trapint_init___trapint(){
        ___X_CMD_REPLHOOK_EXIT_PRECMD=1
        ___X_CMD_REPLHOOK_CAPTURE_INTERRUPT=1
        return 130
    }

    ___x_cmd_replhook_trapint_init___precmd(){
        [ -z "$___X_CMD_REPLHOOK_EXIT_PRECMD" ] || {
            ___X_CMD_REPLHOOK_EXIT_PRECMD=
            return 130
        }

        ___X_CMD_REPLHOOK_CAPTURE_INTERRUPT=
        ___X_CMD_REPLHOOK_EXIT_PRECMD=
        if [ -z "$ZSH_VERSION" ]; then
            [ -z "$___X_CMD_REPLHOOK_PREEXEC_DONE" ] || ___X_CMD_REPLHOOK_TRAPINT_OLD="$(trap)"
            trap '___x_cmd_replhook_debug_inside_trapc(){ return 0; }; ___x_cmd_replhook_trapint_init___trapint; ___x_cmd_replhook_debug_inside_trapc(){ return 1; }' INT;
        else
            [ -z "$___X_CMD_REPLHOOK_PREEXEC_DONE" ] || {
                ___X_CMD_REPLHOOK_TRAPINT_OLD=; trap | {
                    local l; while read -r l; do
                        ___X_CMD_REPLHOOK_TRAPINT_OLD="${___X_CMD_REPLHOOK_TRAPINT_OLD}${l}${___X_CMD_UNSEENCHAR_NEWLINE}"
                    done
                }
            }
            trap '___x_cmd_replhook_trapint_init___trapint || return 130' INT;
        fi
        ___X_CMD_REPLHOOK_PREEXEC_DONE=
    }

    ___x_cmd_replhook_trapint_init___preexec(){
        if ___x_cmd_replhook_debug_inside_trapc; then
            ___X_CMD_REPLHOOK_CAPTURE_INTERRUPT=1
            return
        fi

        ___X_CMD_REPLHOOK_PREEXEC_DONE=1
        if [ -z "$___X_CMD_REPLHOOK_TRAPINT_OLD" ]; then
            trap - INT
        else
            eval "$___X_CMD_REPLHOOK_TRAPINT_OLD"
        fi
    }

    ___x_cmd_replhook_precmd_add    ___x_cmd_replhook_trapint_init___precmd
    ___x_cmd_replhook_preexec_add   ___x_cmd_replhook_trapint_init___preexec
}

if [ -n "$ZSH_VERSION" ]; then
    if ___x_cmd_replhook_enable; then
        ___x_cmd_replhook_trapint_init
    fi
fi
