# shellcheck shell=sh disable=SC2039,SC1090,SC3043,SC2263

# x free - Display memory usage in Linux free command format

xrc:mod:lib     free    top

___x_cmd log init free

___X_CMD_FREE_AWKDIR="$___X_CMD_ROOT_MOD/free/lib/awk"

___x_cmd_free___main(){
    [ "$#" -gt 0 ] || set -- run

    local op="$1"; shift
    local top_n_arg=
    case "$op" in
        top)
            if [ $# -gt 0 ]; then
                if [ "$1" = "all" ]; then
                    top_n_arg=999999; shift
                elif [ "$1" -gt 0 ] 2>/dev/null; then
                    top_n_arg="$1"; shift
                fi
            fi
            op="run"
            ;;
    esac

    # Parse all options
    local format="table"
    local header=1
    local human=0
    local seconds=0
    local count=0
    local top_n="${top_n_arg:-10}"
    local group="auto"
    local filter=""
    local use_rss=0
    local use_fp=0
    local expert=0

    # Put $op back for parsing
    set -- "$op" "$@"

    while [ $# -gt 0 ]; do
        case "$1" in
            --csv)          format="csv";       shift ;;
            --tsv)          format="tsv";       shift ;;
            --no-header)    header=0;           shift ;;
            -s|--seconds)   seconds="$2"; arg:2:shift ;;
            -c|--count)     count="$2";   arg:2:shift ;;
            -n|--top)
                top_n="$2"
                [ "$top_n" = "all" ] && top_n=999999
                arg:2:shift
                ;;
            -g|--group)     group="$2";   arg:2:shift ;;
            -f|--filter)    filter="$2";  arg:2:shift ;;
            -e|--expert)    expert=1;           shift ;;
            --rss)          use_rss=1;          shift ;;
            -p|--precise)   use_fp=1;           shift ;;
            -h|--help)      ___x_cmd help -m free "$@"; return 0 ;;
            run)            shift ;;
            *)              shift ;;
        esac
    done

    # Auto human mode for interactive tty
    if [ "$format" = "table" ] && [ "$human" -eq 0 ] && ___x_cmd_is_stdout2tty; then
        human=1
    fi

    # Platform dispatch
    if ___x_cmd os is darwin; then
        ___x_cmd_free___run_darwin
    else
        ___x_cmd_free___run_linux
    fi

    # Top processes: only in table format (csv/tsv have different schema)
    [ "$format" = "table" ] && ___x_cmd_free___top "$top_n" "$group" "$format" "$header" "$filter" "$use_rss" "$use_fp"
}

___x_cmd_free___run_linux(){
    if [ -r /proc/meminfo ]; then
        ___x_cmd_free___run_loop "linux"
    else
        N=free M="Unable to get memory info" log:ret:1
    fi
}

___x_cmd_free___run_darwin(){
    ___x_cmd_free___run_loop "darwin"
}

___x_cmd_free___run_loop(){
    local platform="$1"
    local iteration=0

    # Default -s 1 when -c is set without -s
    if [ "$count" -gt 0 ] && [ "$seconds" -eq 0 ]; then
        seconds=1
    fi

    while true; do
        if [ "$count" -gt 0 ] && [ "$iteration" -ge "$count" ]; then
            break
        fi

        # Only print header on first iteration
        local current_header="$header"
        if [ "$iteration" -gt 0 ]; then
            current_header=0
        fi

        if [ "$platform" = "darwin" ]; then
            ___x_cmd_free___run_darwin_once "$current_header"
        else
            ___x_cmd_free___run_linux_once "$current_header"
        fi

        iteration=$((iteration + 1))

        if [ "$seconds" -eq 0 ] || ([ "$count" -gt 0 ] && [ "$iteration" -ge "$count" ]); then
            break
        fi

        sleep "$seconds" || return 130
    done
}

___x_cmd_free___run_linux_once(){
    local current_header="${1:-$header}"
    local NO_COLOR=0
    ___x_cmd_is_stdout2tty || NO_COLOR=1
    ___x_cmd_cmds_awk -v format="$format" -v header="$current_header" -v human="$human" -v NO_COLOR="$NO_COLOR" \
        -v expert="$expert" \
        -f "$___X_CMD_FREE_AWKDIR/share.awk" \
        -f "$___X_CMD_FREE_AWKDIR/linux.awk" \
        /proc/meminfo
}

___x_cmd_free___run_darwin_once(){
    local current_header="${1:-$header}"
    local NO_COLOR=0
    ___x_cmd_is_stdout2tty || NO_COLOR=1

    (sysctl \
        hw.pagesize hw.memsize hw.memsize_usable \
        vm.swapusage \
        vm.compressor_pool_size vm.compressor_input_bytes vm.compressor_compressed_bytes \
        vm.vm_page_free_target vm.vm_page_filecache_min \
        vm.page_pageable_internal_count vm.page_reusable_count \
        vm.page_realtime_count vm.page_shared_region_count \
        vm.page_cleaned_count vm.page_free_wanted \
        2>/dev/null; \
     vm_stat 2>/dev/null) | ___x_cmd_cmds_awk \
        -v format="$format" \
        -v header="$current_header" \
        -v human="$human" \
        -v NO_COLOR="$NO_COLOR" \
        -v expert="$expert" \
        -f "$___X_CMD_FREE_AWKDIR/share.awk" \
        -f "$___X_CMD_FREE_AWKDIR/darwin.awk"
}
