#!/usr/bin/env bash
# ...
# shellcheck disable=2317,2059
PING_ITER=16

# Progress bar  dedicated variables
# We can control how progress bar work
PROGRESS_BAR_CHAR=(█ ▒)

# control which information is displayed"
PROGRESS_BAR_DISPLAY_INFO=1
PROGRESS_BAR_DISPLAY_COMPL=1

# Display template
# We can control how informations is displayed
PROGRESS_BAR_INFO_TEMPLATE=' %s [%2d/%2d] '
PROGRESS_BAR_COMPL_TEMPLATE=' %2d%% '
PROGRESS_BAR_TEMPLATE='\033[1m%s%s\033[0m%s%s\r'

command() {
    local -r host=${1?"first parameter must be an host"}
    local -r iteration=${2?"second parameter must be an iteration number"}
    local -r cmd=(ping -c "${iteration}" "${host}")

    "${cmd[@]}"
}

draw_progressbar() {
    # function parameters
    local -r progress=${1?"progress is mandatory"}
    local -r total=${2?"total elements is mandatory"}
    local -r info=${3:-"In progress"}

    # function local variables
    local progress_segment
    local todo_segment
    local info_segment=""
    local compl_segment=""

    if [[ ${PROGRESS_BAR_DISPLAY_INFO:-1} -eq 1 ]]; then
        printf -v info_segment "${PROGRESS_BAR_INFO_TEMPLATE}" \
            "$info" "$progress" "$total"
    fi

    local -r progress_ratio=$((progress * 100 / total))
    if [[ ${PROGRESS_BAR_DISPLAY_COMPL:-0} -eq 1 ]]; then
        printf -v compl_segment "${PROGRESS_BAR_COMPL_TEMPLATE}" \
            "$progress_ratio"
    fi

    # progress bar construction
    # calculate each element sizes, bar must fit in ou screen
    local -r bar_size=$((COLUMNS - ${#info_segment} - ${#compl_segment}))
    local -r progress_segment_size=$((bar_size * progress_ratio / 100))
    local -r todo_segment_size=$((bar_size - progress_segment_size))
    printf -v progress_segment "%${progress_segment_size}s" ""
    printf -v todo_segment "%${todo_segment_size}s" ""

    printf >&2 "$PROGRESS_BAR_TEMPLATE" \
        "$info_segment" \
        "${progress_segment// /${PROGRESS_BAR_CHAR[0]}}" \
        "${todo_segment// /${PROGRESS_BAR_CHAR[1]}}" \
        "$compl_segment"
}

parse_output() {
    trap change_column_size WINCH
    while read -r line; do
        if [[ "$line" =~ icmp_seq=([[:digit:]]{1,}).*time=(.*) ]]; then
            draw_progressbar \
                "${BASH_REMATCH[1]}" \
                "$PING_ITER" \
                "Ping in progess"
        elif [[ "$line" =~ ^PING(.*\(.*\)).* ]]; then
            printf "Launch ping command to %s with %d iterations\n" \
                "${BASH_REMATCH[1]}" \
                "$PING_ITER"
        elif [[ "$line" =~ .*packets\ transmitted.* ]]; then
            printf >&2 "\033[0K\r"
            printf "%s\n" "$line"
        fi
    done
}

change_column_size() {
    printf >&2 "%${COLUMNS}s" ""
    printf >&2 "\033[0K\r"
    COLUMNS=$(tput cols)
}

main() {
    COLUMNS=$(tput cols)
    command "aquilenet.fr" "$PING_ITER" > >(parse_output)
}

main
exit 0
