
# shellcheck shell=dash disable=SC2317
# 参考pick的设计
# 采用tui table的样例代码
# 后面我们会进行更多的定制，例如选择输出字段，排序，过滤等

# x ja json2csv a.json .a .b .c | x csv app
# x ja json2csv a.json .a .b .c | x csv header --add a b c | x csv app

# x sql select from | x csv app --header a,b,c
# x sql select from | x csv header --add a,b,c | x csv app
# x sql select from | x csv header --mod acde=abc b=c | x csv app

# x csv app --width "100,30,20" --header "AAA,BBB,CCC"  --action c "copy" "Press 'c' to copy to clipboard" cat ./.x-cmd/data.csv
# x csv app --loop-action R "remove" "Remove this" --loop-processor funa -- eval 'ps | x csv convert --col'
# x:loop-request:*

___X_CMD_CSV_APP_EXITCODE_NODATA=254
___x_cmd_csv_app(){
    # local ___X_CMD_CSV_APP_DATA="${___X_CMD_CSV_APP_DATA:-""}"
    local ___X_CMD_CSV_APP_EXITCODE_NODATA="${___X_CMD_CSV_APP_EXITCODE_NODATA}"
    local ___X_CMD_CSV_APP_WIDTH="${___X_CMD_CSV_APP_WIDTH:-""}"
    local ___X_CMD_CSV_APP_HEADER="${___X_CMD_CSV_APP_HEADER:-""}"
    local ___X_CMD_CSV_APP_RET_STYLE="${___X_CMD_CSV_APP_RET_STYLE:-""}"
    local ___X_CMD_CSV_APP_IS_HIDE_INDEX="${___X_CMD_CSV_APP_IS_HIDE_INDEX:-""}"
    local ___X_CMD_CSV_APP_PREVIEW="${___X_CMD_CSV_APP_PREVIEW}"
    local ___X_CMD_CSV_APP_TABLE_VIEW="${___X_CMD_CSV_APP_TABLE_VIEW}"
    local ___X_CMD_CSV_APP_TABLE_WIDTH="${___X_CMD_CSV_APP_TABLE_WIDTH}"

    local ___X_CMD_CSV_APP_ACTION="${___X_CMD_CSV_APP_ACTION:-""}"
    local ___X_CMD_CSV_APP_PROCESSOR="${___X_CMD_CSV_APP_PROCESSOR:-""}"
    local ___X_CMD_CSV_APP_LOOP_ACTION="${___X_CMD_CSV_APP_LOOP_ACTION:-""}"
    local ___X_CMD_CSV_APP_LOOP_PROCESSOR="${___X_CMD_CSV_APP_LOOP_PROCESSOR:-""}"

    local ___X_CMD_CSV_APP_SW_CLEAR_ON_EXIT=
    local ___X_CMD_CSV_APP_SW_CLEAR_ON_CTRL_C=
    local ___X_CMD_CSV_APP_CONTINUE_NAME=

    local NL="${___X_CMD_UNSEENCHAR_NEWLINE}"

    local ___X_CMD_CSV_APP_HOOK_BEGIN=
    local ___X_CMD_CSV_APP_HOOK_END=
    local op; while op="$1"; do
        case "$op" in
            -b|--begin)     ___X_CMD_CSV_APP_HOOK_BEGIN="$2"
                            [ -n "$___X_CMD_CSV_APP_HOOK_BEGIN" ] || N=csv M="Provide csv tui hook begin function name" log:ret:64
                            shift 2 ;;
            -e|--end)       ___X_CMD_CSV_APP_HOOK_END="$2"
                            [ -n "$___X_CMD_CSV_APP_HOOK_END" ] || N=csv M="Provide csv tui hook end function name" log:ret:64
                            shift 2 ;;
            --clear)        ___X_CMD_CSV_APP_SW_CLEAR_ON_EXIT=1
                            shift ;;
            --ctrl-c-clear) ___X_CMD_CSV_APP_SW_CLEAR_ON_CTRL_C=1
                            shift ;;
            --width)        ___X_CMD_CSV_APP_WIDTH="$2";
                            [ -n "$___X_CMD_CSV_APP_WIDTH" ] || N=csv M="Provide csv column width" log:ret:64
                            shift 2 ;;
            --header)       ___X_CMD_CSV_APP_HEADER="$2";
                            [ -n "$___X_CMD_CSV_APP_HEADER" ] || N=csv M="Provide csv header name" log:ret:64
                            shift 2 ;;
            --return)       ___X_CMD_CSV_APP_RET_STYLE="$2";
                            [ -n "$___X_CMD_CSV_APP_RET_STYLE" ] || N=csv M="Provide the style to be selected and returned, [line|print|var]" log:ret:64
                            shift 2 ;;
            --hide_index)   ___X_CMD_CSV_APP_IS_HIDE_INDEX=1;
                            shift ;;
            --action)
                            [ -n "$2" ] || N=csv M="Provide the action key" log:ret:64
                            [ -n "$3" ] || N=csv M="Provide a short description about this action key" log:ret:64
                            [ -n "$4" ] || N=csv M="Provide a log description about this action key" log:ret:64
                            ___X_CMD_CSV_APP_ACTION="${___X_CMD_CSV_APP_ACTION}${2}${NL}${3}${NL}${4}${NL}"
                            shift 4 ;;
            --processor)    ___X_CMD_CSV_APP_PROCESSOR="$2";
                            [ -n "$___X_CMD_CSV_APP_PROCESSOR" ] || N=csv M="Provide the processor function name" log:ret:64
                            shift 2 ;;
            --continue)     ___X_CMD_CSV_APP_CONTINUE_NAME="$2"
                            [ -n "$___X_CMD_CSV_APP_CONTINUE_NAME" ] || N=csv M="Provide the csvapp name" log:ret:64
                            shift 2 ;;
            --datafile)     ___X_CMD_CSV_APP_DATAFILE="$2"
                            [ -n "$___X_CMD_CSV_APP_DATAFILE" ] || N=csv M="Provide datafile to csv app" log:ret:64
                            shift 2 ;;
            --preview)      ___X_CMD_CSV_APP_PREVIEW="$2";
                            [ -n "$___X_CMD_CSV_APP_PREVIEW" ] || N=csv M="Provide csv header name of preview data" log:ret:64
                            shift 2 ;;
            --table-view)   ___X_CMD_CSV_APP_TABLE_VIEW="$2";
                            [ -n "$___X_CMD_CSV_APP_TABLE_VIEW" ] || N=csv M="Provide csv header name of table data" log:ret:64
                            shift 2 ;;
            --table-width)  ___X_CMD_CSV_APP_TABLE_WIDTH="$2";
                            [ -n "$___X_CMD_CSV_APP_TABLE_WIDTH" ] || N=csv M="Provide csv app table width" log:ret:64
                            shift 2 ;;
            --loop-action)
                            [ -n "$2" ] || N=csv M="Provide the loop action key" log:ret:64
                            [ -n "$3" ] || N=csv M="Provide a short description about this loop action key" log:ret:64
                            [ -n "$4" ] || N=csv M="Provide a log description about this loop action key" log:ret:64
                            ___X_CMD_CSV_APP_LOOP_ACTION="${___X_CMD_CSV_APP_LOOP_ACTION}${2}${NL}${3}${NL}${4}${NL}"
                            shift 4 ;;
            --loop-processor)
                            ___X_CMD_CSV_APP_LOOP_PROCESSOR="$2";
                            [ -n "$___X_CMD_CSV_APP_LOOP_PROCESSOR" ] || N=csv M="Provide the loop processor function name" log:ret:64
                            shift 2 ;;
            -h|--help)      M='csv app' help:ret:0 ;;
            --)             shift; break ;;
            --*)            N=csv M="Not support [option=$1]" log:ret:64 ;;
            *)              break
        esac
    done

    [ "$___X_CMD_CSV_APP_RET_STYLE" != "print" ] || local ___X_CMD_CSV_APP_DATA_CURROW=
    local x_=;
    if [ -z "$___X_CMD_CSV_APP_LOOP_PROCESSOR" ]; then
        ___x_cmd storerat_ ___x_cmd_csv_app_ "$@" || return $?
        eval "$x_" || return $?
    else
        local ___X_CMD_CSV_APP_IS_LOOP=
        local ___X_CMD_CSV_APP_LOOP_PROCESSOR_ARG=
        while true; do
            ___X_CMD_CSV_APP_IS_LOOP=
            ___X_CMD_CSV_APP_LOOP_PROCESSOR_ARG=
            ___X_CMD_CSV_APP_DATA_CURROW=
            x_=; ___x_cmd storerat_ ___x_cmd_csv_app_ "$@" || return $?
            eval "$x_" || return $?
            [ -n "$___X_CMD_CSV_APP_IS_LOOP" ] || break
            "$___X_CMD_CSV_APP_LOOP_PROCESSOR" "$___X_CMD_CSV_APP_LOOP_PROCESSOR_ARG" || return $?
        done
    fi

    [ "$___X_CMD_CSV_APP_RET_STYLE" != "print" ] || [ -z "$___X_CMD_CSV_APP_DATA_CURROW" ] || printf "%s\n" "$___X_CMD_CSV_APP_DATA_CURROW";
}

___x_cmd_csv_app_(){
    # ___X_CMD_CSV_APP_DATA="$___X_CMD_CSV_APP_DATA" \
    NO_COLOR="$NO_COLOR" \
    ___X_CMD_CSV_APP_WIDTH="$___X_CMD_CSV_APP_WIDTH" \
    ___X_CMD_CSV_APP_HEADER="$___X_CMD_CSV_APP_HEADER" \
    ___X_CMD_CSV_APP_PREVIEW="$___X_CMD_CSV_APP_PREVIEW" \
    ___X_CMD_CSV_APP_TABLE_VIEW="$___X_CMD_CSV_APP_TABLE_VIEW" \
    ___X_CMD_CSV_APP_TABLE_WIDTH="$___X_CMD_CSV_APP_TABLE_WIDTH" \
    ___X_CMD_CSV_APP_RET_STYLE="$___X_CMD_CSV_APP_RET_STYLE" \
    ___X_CMD_CSV_APP_IS_HIDE_INDEX="$___X_CMD_CSV_APP_IS_HIDE_INDEX" \
    ___X_CMD_CSV_APP_ACTION="$___X_CMD_CSV_APP_ACTION" \
    ___X_CMD_CSV_APP_PROCESSOR="$___X_CMD_CSV_APP_PROCESSOR" \
    ___X_CMD_CSV_APP_LOOP_ACTION="$___X_CMD_CSV_APP_LOOP_ACTION" \
    ___X_CMD_CSV_APP_LOOP_PROCESSOR="$___X_CMD_CSV_APP_LOOP_PROCESSOR" \
    ___X_CMD_CSV_APP_SW_CLEAR_ON_EXIT="$___X_CMD_CSV_APP_SW_CLEAR_ON_EXIT" \
    ___X_CMD_CSV_APP_SW_CLEAR_ON_CTRL_C="$___X_CMD_CSV_APP_SW_CLEAR_ON_CTRL_C" \
    ___X_CMD_CSV_APP_CONTINUE_NAME="$___X_CMD_CSV_APP_CONTINUE_NAME" \
    ___X_CMD_CSV_APP_HOOK_BEGIN="$___X_CMD_CSV_APP_HOOK_BEGIN" \
    ___X_CMD_CSV_APP_HOOK_END="$___X_CMD_CSV_APP_HOOK_END" \
    ___X_CMD_CSV_APP_DATAFILE="$___X_CMD_CSV_APP_DATAFILE" \
    ___X_CMD_CSV_APP_EXITCODE_NODATA="$___X_CMD_CSV_APP_EXITCODE_NODATA" \
    ___X_CMD_SHBIN_CODE='
        xrc csv ;
        '"$___X_CMD_CSV_APP_SHBIN_CODE"'
        "$@"
    ' ___x_cmd antizshbin ___x_cmd_csv_app___run "$@"
}

___x_cmd_csv_app___run(){
    local ___X_CMD_TUI_CSV_POSITION=
    local ___X_CMD_TUI_CURRENT_CSV_POSITION=
    local ___X_CMD_CSV_APP_DATA=""
    if [ -z "${___X_CMD_CSV_APP_DATAFILE}${___X_CMD_CSV_APP_DATA}" ]; then
        [ "$#" -gt 0 ] || {
            if [ -t 0 ]; then   ___x_cmd help -m csv app >&2; return 1
            else                set - ___x_cmd_cmds_cat
            fi
        }
        ___X_CMD_CSV_APP_DATA="$("$@" | command tr -d '\0' 2>/dev/null)" || return $?
        [ -n "$___X_CMD_CSV_APP_DATA" ] || {
            ___x_cmd log :csv info "The CSV table is empty. Exiting the interactive application"
            return "$___X_CMD_CSV_APP_EXITCODE_NODATA"
        }
    fi

    [ -z "$___X_CMD_CSV_APP_CONTINUE_NAME" ] || {
        x_=; ___x_cmd tui position get_ "csvapp_${___X_CMD_CSV_APP_CONTINUE_NAME}"
        ___X_CMD_TUI_CSV_POSITION="$x_"
    }

    local ___X_CMD_CSV_APP_RET_VAL=; local ___X_CMD_CSV_APP_TMP_EXITCODE=; local ___X_CMD_TUI_APP_IS_SMALL_SCREEN=
    ___x_cmd_tui_app_processer(){ ___x_cmd_csv_tui_app_processer "$@"; }
    </dev/tty \
    ___X_CMD_CSV_APP_PREVIEW="$___X_CMD_CSV_APP_PREVIEW" \
    ___X_CMD_CSV_APP_TABLE_VIEW="$___X_CMD_CSV_APP_TABLE_VIEW" \
    ___X_CMD_CSV_APP_TABLE_WIDTH="$___X_CMD_CSV_APP_TABLE_WIDTH" \
    ___X_CMD_CSV_APP_IS_HIDE_INDEX="$___X_CMD_CSV_APP_IS_HIDE_INDEX" \
    ___X_CMD_CSV_APP_WIDTH="$___X_CMD_CSV_APP_WIDTH" \
    ___X_CMD_CSV_APP_RET_STYLTUI_PANIC_TEXTE="$___X_CMD_CSV_APP_RET_STYLE" \
    ___X_CMD_CSV_APP_ACTION="$___X_CMD_CSV_APP_ACTION" \
    ___X_CMD_CSV_APP_LOOP_ACTION="$___X_CMD_CSV_APP_LOOP_ACTION" \
    ___X_CMD_CSV_APP_EXITCODE_NODATA="$___X_CMD_CSV_APP_EXITCODE_NODATA" \
    ___X_CMD_TUI_CSV_POSITION="$___X_CMD_TUI_CSV_POSITION" \
    ___x_cmd tui bigapp \
        ${___X_CMD_CSV_APP_SW_CLEAR_ON_EXIT:+"--clear-on-exit"} \
        ${___X_CMD_CSV_APP_SW_CLEAR_ON_CTRL_C:+"--clear-on-ctrl-c"} \
        ${___X_CMD_CSV_APP_HOOK_BEGIN:+"--begin"}   ${___X_CMD_CSV_APP_HOOK_BEGIN:+"$___X_CMD_CSV_APP_HOOK_BEGIN"} \
        ${___X_CMD_CSV_APP_HOOK_END:+"--end"}       ${___X_CMD_CSV_APP_HOOK_END:+"$___X_CMD_CSV_APP_HOOK_END"} \
        -f "$___X_CMD_ROOT_MOD/awk/lib/csv.awk"   \
        -f "$___X_CMD_ROOT_MOD/tui/lib/eg.comp/table.comp.awk" \
        -f "$___X_CMD_ROOT_MOD/csv/lib/awk/csv_util.awk" \
        -f "$___X_CMD_ROOT_MOD/csv/lib/awk/app.awk"
    ___X_CMD_CSV_APP_TMP_EXITCODE="$?"

    unset -f ___x_cmd_tui_app_processer
    [ -z "$___X_CMD_CSV_APP_CONTINUE_NAME" ] || {
        ___x_cmd tui position store "csvapp_${___X_CMD_CSV_APP_CONTINUE_NAME}" "$___X_CMD_TUI_CURRENT_CSV_POSITION"
    }

    [ -z "$___X_CMD_TUI_APP_IS_SMALL_SCREEN" ] || ___x_cmd_csv_tui___run_print | ___x_cmd csv static_tab
    return "$___X_CMD_CSV_APP_TMP_EXITCODE"
}

___x_cmd_csv_tui___run_print(){
    if [ -f "$___X_CMD_CSV_APP_DATAFILE" ]; then
        ___x_cmd_cmds_cat "$___X_CMD_CSV_APP_DATAFILE"
    elif [ -n "$___X_CMD_CSV_APP_DATA" ]; then
        if [ -n "$___X_CMD_CSV_APP_HEADER" ]; then
            printf "%s\n" "$___X_CMD_CSV_APP_DATA" | ___x_cmd csv header "$___X_CMD_CSV_APP_HEADER"
        else
            printf "%s\n" "$___X_CMD_CSV_APP_DATA"
        fi
    fi
}

# x:request:<char-value>\001<cur-cell>\001<cur-row>
# printf "%s\n" "exitcode:0"
# printf "%s\n" "errexit:log text"
___x_cmd_csv_tui_app_processer(){
    case "$1" in
        data:request:*)
            printf "data:start:%s\n" "1"
            ___x_cmd_csv_tui___run_print
            ;;

        *)
            if [ -n "$___X_CMD_CSV_APP_PROCESSOR" ]; then
                "$___X_CMD_CSV_APP_PROCESSOR" "$@"
            fi
            ;;
    esac
}
