# shellcheck shell=dash disable=SC2016

xrc cawk
command -v ___x_cmd_tui_app_processer >/dev/null || ___x_cmd_tui_app_processer(){   $1;   }

___x_cmd_tui_app___has_2(){
    local arg
    for arg in "$@"; do
        case "$arg" in
            --|-)       return 0 ;;
        esac
    done
    return 1
}

___x_cmd_tui_app(){
    ___x_cmd_runmode_allow_manual || N=tui M="The tui function can only be used in manual mode" log:ret:1
    local hook_begin=___x_cmd_tui_app_begin
    local hook_end=___x_cmd_tui_app_end
    if ___x_cmd_tui_app___has_2 "$@"; then
        while [ $# -gt 0 ]; do
            case "$1" in
                -b|--begin)     hook_begin="$2";  shift 2                 ;;
                -e|--end)       hook_end="$2";    shift 2                 ;;
                --)             shift; break ;;
                *)              N=tui M="Unknown argument $1" log:ret:64    ;;
            esac
        done
    fi

    ___x_cmd_tui_util___acquire_old_trap
    trap '' INT
    local ___X_CMD_TUI_APP_TMP_EXITCODE=0

    ! ___x_cmd_hascmd "$hook_begin"    || "$hook_begin"
    local x_=; < "$___X_CMD_DEVTTY_FP" ___x_cmd storerat_ ___x_cmd_tui_app_main "$@" || return $?
    eval "$x_"
    ! ___x_cmd_hascmd "$hook_end"      || "$hook_end"

    # UI_CURSOR_NORMAL UI_LINEWRAP_ENABLE
    printf "\033[34h\033[?25h\033[?7h" >&2

    ___x_cmd_tui_util___release_old_trap
    return "$___X_CMD_TUI_APP_TMP_EXITCODE"
}

___x_cmd_tui_app_main_clock___inner(){
    ___x_cmd tty update
    printf "${___X_CMD_UNSEENCHAR_001}%02d${___X_CMD_UNSEENCHAR_001}%d${___X_CMD_UNSEENCHAR_001}%d${___X_CMD_UNSEENCHAR_001}%d\n" \
        "${i}" "$LINES" "$COLUMNS" "$exchange"
    exchange=0
}

___x_cmd_tui_app_main_clock(){
    ___x_cmd pidofsubshell
    local exchange=0;   trap 'i=$(( ((i+1)<100) ? i+1: 0 )); exchange=1 ___x_cmd_tui_app_main_clock___inner;'   USR1    # Data Exchange
    local on=1;         trap 'on='          USR2

    local i=0
    while [ -n "$on" ]; do
        i=$(( ((i+1)<100) ? i+1: 0 ))
        {
            ___x_cmd_tui_app_main_clock___inner
            sleep 0.1
        } &         # 0.05, 0.2
        exchange=0
        wait
    done
}

___x_cmd_tui_app_processer_record()(
    [ ! -f "$___X_CMD_TUI_EXCHAGE_STORE_DEFAULT/$PID_OF_GETLOOP/process_halt" ] || return 0
    local fp="$___X_CMD_TUI_EXCHAGE_STORE_DEFAULT/$PID_OF_GETLOOP/process_id"
    ___x_cmd ensurefp "$fp"
    ___x_cmd pidofsubshell >> "$fp"
    "$@" 2>/dev/null || true
)

___x_cmd_tui_app_processer_kill(){
    local fp="$___X_CMD_TUI_EXCHAGE_STORE_DEFAULT/$PID_OF_GETLOOP/process_id"
    [ -f "$fp" ] || return $?
    local pid=; while read -r pid; do
        ___x_cmd kill -r -s TERM "$pid" || true
    done < "$fp"
    ___x_cmd rmrf "$fp"
}

___x_cmd_tui_app_main_processcmd(){
    ___X_CMD_TUI_APP_TMP_CMD=
    local tmpline; while read -r tmpline; do
        [ "$tmpline" != "$INDICATOR_CMD" ] || break
        ___X_CMD_TUI_APP_TMP_CMD="${___X_CMD_TUI_APP_TMP_CMD}${___X_CMD_UNSEENCHAR_NEWLINE}${tmpline}"
    done
}

___x_cmd_tui_app_main_processeval(){
    local tmpline; while read -r tmpline; do
        [ "$tmpline" != "$INDICATOR_FINALCMD" ] || break
        ___X_CMD_TUI_APP_TMP_FINALCMD="${___X_CMD_TUI_APP_TMP_FINALCMD}${___X_CMD_UNSEENCHAR_NEWLINE}${tmpline}"
    done
}

___X_CMD_TUI_EXCHAGE_STORE_DEFAULT="$___X_CMD_ROOT_TMP/tui/store/exchange"

xrc wchar
___x_cmd_tui_app_main___input()(
    trap '' INT             # Interrupt by user
    ___x_cmd pidofsubshell
    ___x_cmd_tui_app_main_clock &
    ___x_cmd_wchar___getloop_native   # I think this should be reintroduce into this.
)

___x_cmd_tui_app_main(){
    local INDICATOR_SIGNAL="$___X_CMD_UNSEENCHAR_001"
    local INDICATOR_CMD="${___X_CMD_UNSEENCHAR_001}${___X_CMD_UNSEENCHAR_001}${___X_CMD_UNSEENCHAR_001}"
    local INDICATOR_FINALCMD="${___X_CMD_UNSEENCHAR_001}${___X_CMD_UNSEENCHAR_001}${___X_CMD_UNSEENCHAR_001}${___X_CMD_UNSEENCHAR_001}"
    {
        < "$___X_CMD_DEVTTY_FP" ___x_cmd_tui_app_main___input 2>/dev/null   # In order to hide the log of the kill signal in the dash environment.
    } | {
        trap '' INT
        read -r PID_OF_GETLOOP;     read -r PID_OF_CLOCK
        printf "%s\n%s\n" "$PID_OF_GETLOOP" "$PID_OF_CLOCK"

        local EXCHANGE_DIR; EXCHANGE_DIR="$___X_CMD_TUI_EXCHAGE_STORE_DEFAULT/$PID_OF_GETLOOP"
        ___x_cmd mkdirp "$EXCHANGE_DIR"

        printf "\r\0337" >&2     # Save Posistion
        ___x_cmd tty update
        ___x_cmd_tui_app_main___awk "$@"
        printf "%s\n" "" > "$EXCHANGE_DIR/process_halt"
        printf "%s\n%s\n%s\n" "$INDICATOR_FINALCMD" "___X_CMD_TUI_APP_TMP_EXITCODE=$?" "$INDICATOR_FINALCMD"
        ___x_cmd_tui_app_processer_kill 2>/dev/null
    } | {
        trap '' INT
        read -r PID_OF_GETLOOP;     read -r PID_OF_CLOCK

        ___X_CMD_TUI_APP_TMP_ACC=0
        allow_to_send=1


        local ___X_CMD_TUI_APP_TMP_CMD;     local ___X_CMD_TUI_APP_TMP_OUT
        local ___X_CMD_TUI_APP_TMP_FINALCMD

        local tmpline; while read -r tmpline; do
            case "$tmpline" in
                "$INDICATOR_SIGNAL")        allow_to_send=1 ;;
                "$INDICATOR_CMD")
                                            ___x_cmd_tui_app_main_processcmd
                                            read -r ___X_CMD_TUI_APP_TMP_OUT
                                            ___x_cmd_tui_app_processer_record \
                                                ___x_cmd_tui_app_processer "${___X_CMD_TUI_APP_TMP_CMD#*"${___X_CMD_UNSEENCHAR_NEWLINE}"}" >"${___X_CMD_TUI_APP_TMP_OUT}" 2>/dev/null
                                            ___X_CMD_TUI_APP_TMP_ACC=$(( ___X_CMD_TUI_APP_TMP_ACC+1 ))
                                            ;;
                "$INDICATOR_FINALCMD")      ___x_cmd_tui_app_main_processeval
                                            ;;
                *)                          tui:warn "Unknown instruction -> $tmpline"
            esac

            if [ "$___X_CMD_TUI_APP_TMP_ACC" -gt 0 ] && [ -n "$allow_to_send" ]; then
                ___X_CMD_TUI_APP_TMP_ACC=$(( ___X_CMD_TUI_APP_TMP_ACC-1 ))
                kill -s USR1 "$PID_OF_CLOCK" 2>/dev/null    # Data Exchange
                allow_to_send=
            fi
        done

        printf "%s\n" "${___X_CMD_TUI_APP_TMP_FINALCMD#*"${___X_CMD_UNSEENCHAR_NEWLINE}"}"
        kill -s KILL "$PID_OF_GETLOOP" 2>/dev/null; kill -s USR2 "$PID_OF_CLOCK" 2>/dev/null     # Shutdown everything. TERM

        ___x_cmd rmrf "${___X_CMD_TUI_EXCHAGE_STORE_DEFAULT}/$PID_OF_GETLOOP"
    }

    ___x_cmd_cmds stty -raw 2>/dev/null   # TODO: Using better method than kill -9 on getloop
    ___x_cmd_cmds stty -istrip 2>/dev/null
    ___x_cmd_cmds stty echo 2>/dev/null
    return 0
}

___x_cmd_tui_app_main___awk(){
    ___x_cmd cawk --interactive --locale utf8   \
        -v ROWS="$LINES" -v COLS="$COLUMNS"     \
        -v IS_TH_NO_COLOR="$NO_COLOR"           \
        -v FOLDER_ROOT="${EXCHANGE_DIR}/"       \
        -f "$___X_CMD_ROOT_MOD/awk/lib/sh.awk"              \
        -f "$___X_CMD_ROOT_MOD/awk/lib/k.awk"               \
        -f "$___X_CMD_ROOT_MOD/awk/lib/ui/ui.awk"           \
        -f "$___X_CMD_ROOT_MOD/awk/lib/ui/cursor.awk"       \
        -f "$___X_CMD_ROOT_MOD/awk/lib/u/u8wc.awk"          \
        -f "$___X_CMD_ROOT_MOD/awk/lib/u/wcwidth.awk"       \
        -f "$___X_CMD_ROOT_MOD/tui/lib/draw.awk"            \
        -f "$___X_CMD_ROOT_MOD/tui/lib/painter.awk"         \
        -f "$___X_CMD_ROOT_MOD/tui/lib/ctrl.awk"            \
        -f "$___X_CMD_ROOT_MOD/tui/lib/layout.awk"          \
        -f "$___X_CMD_ROOT_MOD/tui/lib/model.awk"           \
        -f "$___X_CMD_ROOT_MOD/tui/lib/comp/share.awk"      \
        "$@" \
        -f "$___X_CMD_ROOT_MOD/tui/lib/app.awk"
}
