#!/bin/bash

# updater_shlip
#
# helper script to define utility functions
#
# part of mx-updater package
#
# this bash scripted is meant to be "sourced"
# at /usr/lib/mx-updater/shlib/updater_shlib

mygettext() {
    local gettext=gettext
    $gettext -d mx-updater "$@"
}

unset UPDATER_SHLIB_DEBUG

debug() {
    # a simple echo debug function
    [ -z "${UPDATER_SHLIB_DEBUG}" ] && return 0
    local func=$1;     shift
    echo "[DEBUG:$func]" "$@" >&2
    return 0
}

warn() {
    # a simple echo debug 'warn' function
    local func=$1;     shift
    echo "[WARN:$func]" "$@" >&2
    return 0
}

get_config_item() {

    local config_item=$1
    local default_value=$2

    local LC_CTYPE="C.UTF-8"
    local LC_COLLATE="C.UTF-8"

    local CONFIG_DIST="MX-Linux"              # dist name where conf file is located und ~/.config
    local CONFIG_NAME="mx-updater.conf"       # conf file name
    local CONFIG_SECTION="Settings"           # section within

    local home_dir="$(eval echo ~$(logname))"
    local config_file="${home_dir}/.config/${CONFIG_DIST}/${CONFIG_NAME}"

    local SED_ITEM_PATTERN="[0-9a-zA-Z_]+"    # only digits, letter, and underscore for items
    local SED_VALUE_PATTERN="[0-9a-zA-Z_-]+"  # like above, but additionally with an "-" hyphen

    debug "get_config_item" "Got config_item '$config_item' default_value '$default_value'"  >&2
    debug "get_config_item" "config_file is '$config_file'"  >&2

    # trim both left and right whitespace
    # like key=$(echo "$key" | xargs)
    config_item="${config_item#"${config_item%%[![:space:]]*}"}"
    config_item="${config_item%"${config_item##*[![:space:]]}"}"
    debug "get_config_item" "Got config_item '$config_item'"  >&2

    if [ -z "$config_item" ]; then
        warn "get_config_item" "need a parameter" >&2
        return 1
    fi

    if ! [[ "$config_item" =~ ^${SED_ITEM_PATTERN}$ ]]; then
        warn "get_config_item" "need a valid config item as parameter (pattern '${SED_ITEM_PATTERN}', got '$config_item' " >&2
        return 1
    fi
    local SED_KEY_PATTERN="$config_item"

    if [ -z "${default_value}" ]; then
        warn "get_config_item" "need a valid default value, got empty string '$default_value' " >&2
        return 1
    fi

    # trim whitespaces
    default_value="${default_value#"${default_value%%[![:space:]]*}"}"
    default_value="${default_value%"${default_value##*[![:space:]]}"}"

    if ! [[ "$default_value" =~ ^${SED_VALUE_PATTERN}$ ]]; then
        warn "get_config_item" "need a valid default value (pattern '${SED_VALUE_PATTERN}'), got '$default_value' " >&2
        return 1
    fi


    # If config file doesn't exist, return default settings
    if [ ! -f "$config_file" ]; then
        #warn "get_config_item" "Config file '$config_file' not found or is not a regular file. Using default value: '$default_value'" >&2
        echo "$default_value"
        return 0
    fi

    if [ ! -r "$config_file" ]; then
        #warn "get_config_item" "Config file '$config_file' not readable. Using default: '$default_value'" >&2
        echo "$default_value"
        return 0
    fi

    if [ ! -s "$config_file" ]; then
        #warn "get_config_item" "Config file '$config_file' is empty. Using default: '$default_value'" >&2
        echo "$default_value"
        return 0
    fi


    IFS=$'\t' read -r key value < <(
                sed -nr "/^[[]${CONFIG_SECTION}[]]/,/^[[]/{
                    s/\s*//g;
                    s/^(${SED_KEY_PATTERN})=(${SED_VALUE_PATTERN})/\1\t\2/p
                    }" "$config_file" # 2>/dev/null
                    )

    debug "get_config_item" "Got key '$key' value '$value'"  >&2

    # trim both left and right whitespace
    # value=$(echo "$value" | xargs)
    value="${value#"${value%%[![:space:]]*}"}"
    value="${value%"${value##*[![:space:]]}"}"

    if ! [[ "$value" =~ ^[0-9a-zA-Z_-]+$ ]]; then
        value="$default_value"
    fi

    echo "$value"

    # return success
    return 0
}



press_any_key_stop_auto_close() {
    local default_timeout=10

    if [ -z "${AUTO_CLOSE_TIMEOUT}" ]; then
        read -r AUTO_CLOSE_TIMEOUT < <(get_config_item "auto_close_timeout" "$default_timeout")
    fi
    if [ -z "${AUTO_CLOSE_TIMEOUT}" ]; then
        AUTO_CLOSE_TIMEOUT=$default_timeout
    fi
    if [ -n "${AUTO_CLOSE_TIMEOUT//[0-9]/}" ]; then
        AUTO_CLOSE_TIMEOUT=$default_timeout
    fi

    local count_timeout=${AUTO_CLOSE_TIMEOUT:0:9}

    local length_timeout=${#count_timeout}
    local count_str='<'
    local count_len=24
    local cols=$(/usr/bin/tput cols)
    local count_line=$(printf "$count_str%.0s" $(eval echo {1..$count_len}));
    local space_line=$(printf '%*s' $cols)
    local done_line=$(printf '_''%.0s' $(eval echo {1..$cols}))
    export TEXTDOMAIN="mx-updater"
    local anykey_to_stop=$(gettext "press any key to stop automatic closing")
    local anykey_to_close=$(gettext "press any key to close")

    anykey_to_stop="${anykey_to_stop^}..."
    anykey_to_close="${anykey_to_close^}..."

    local count_down=$count_timeout
    local cntd_line
    local cntd_space_line

    local break_line="false"
    (( count_len + 3 + ${#anykey_to_stop} + 20 >= cols )) && break_line="true"

    if $break_line; then  echo "$anykey_to_stop"; fi
    i=0
    (( count_timeout < 1 )) &&  count_timeout=1
    while (( i++ <  count_timeout+1)); do
        (( count_str_len = count_len - ( (i-1) * count_len) /count_timeout ))
        (( spc_len = count_len - count_str_len ))
        cntd_line="${count_line:0:$count_str_len}";
        cntd_done_line="${done_line:0:$spc_len}"
        if $break_line; then
           printf $'\r'"${cntd_line}${cntd_done_line}: %${length_timeout}i" $count_down;
        else
           printf $'\r'"%${length_timeout}i ${cntd_line}${cntd_done_line}: $anykey_to_stop" $count_down;
        fi

        (( count_down = count_timeout-i))
        read -sr -t1 -n1 && break;
    done && printf $'\r'"$space_line" || return 0
    printf $'\r'"$space_line"
    return 1
}

press_any_key_to_close() {

    export TEXTDOMAIN="mx-updater"
    local cls_msg_en="press any key to close"
    local cls_msg=$(gettext "press any key to close")
    # capitilize
    cls_msg=${cls_msg^}

    # add ellipses
    cls_msg="${cls_msg^}..."
    # TEST
    # cls_msg="${cls_msg} [$UPDATER_AUTO_CLOSE_TIMEOUT] $USER@$HOME"

    read -rsn 1 -p $'\r'"$cls_msg" -t 999999
    return 0
}

translate() {
    local text="$1"
    local domain="MX"

    text=$(mygettext "$text")
    # check DOMAIN is set - but could be  empty
    [ -z "${DOMAIN+set}" ] && echo "$text" && return
    # check text contains $domain
    [ "${text}" == "${text/$domain}" ] && echo $text && return
    text="${text//$domain /$DOMAIN }"
    text="${text// $domain/ $DOMAIN}"
    text="${text/  / }"
    echo "$text"
}



updater_get_screen_info()
{
# Usage
# read -r DW DH XOFF YOFF < <(updater_get_screen_info)
/usr/bin/python3 -c "
from PyQt6.QtWidgets import QApplication
from PyQt6.QtGui import QGuiApplication
app = QApplication([])
primary_screen = QGuiApplication.primaryScreen()
geo = primary_screen.availableGeometry()
print(f'{geo.width()} {geo.height()} {geo.x()} {geo.y()}'
)"
}

updater_show() {

    local msg="$1"
    local cmd="$2"
    local title="$3"
    local icon="$4"
    local icon_kde="$5"

    local T="$title"
    local I="$icon"

    read -r DW DH XOFF YOFF < <(updater_get_screen_info)

    # xdo
    # read DW DH < <(xdotool getdisplaygeometry)
    #if [ -z "$DW" ]; then
    #    sleep 2
    #    read DW DH < <(xdotool getdisplaygeometry)
    #fi

    local terminal_size=$(get_config_item "terminal_size" "two-thirds")
    local terminal_position=$(get_config_item "terminal_position" "center")
    local use_own_geometry=false

    # On Wayland the compositor ignores position hints; ignore any saved position
    if [ -n "$WAYLAND_DISPLAY" ] || [ "${XDG_SESSION_TYPE}" = "wayland" ]; then
        terminal_position="center"
    fi

    case "$terminal_size" in
        one-third)      TW=$((DW/3));    TH=$((DH/3))    ;;
        half)           TW=$((DW/2));    TH=$((DH/2))    ;;
        two-thirds)     TW=$((DW*2/3));  TH=$((DH*2/3))  ;;
        three-quarters) TW=$((DW*3/4));  TH=$((DH*3/4))  ;;
        nine-tenths)    TW=$((DW*9/10)); TH=$((DH*9/10)) ;;
        full)           TW=$DW;          TH=$DH           ;;
        own)            use_own_geometry=true              ;;
        *)              # default: original sizing, capped on large screens
                        TW=$((DW*2/3)); TH=$((DH*2/3))
                        if ((DW >= 1600)); then
                            TW=$(( 1600 * 3 / 5 ))
                            TH=$((  900 * 2 / 3 ))
                        fi
                        ;;
    esac

    # read -r XOFF YOFF < <(xrandr | sed -n -r '/connected primary/{/.*[0-9]+x[0-9]+\+([0-9]+)\+([0-9]+).*/{s::\1 \2:p;q}}')

    : ${XOFF:=0}
    : ${YOFF:=0}

    if ! $use_own_geometry; then
        if [ "$terminal_size" = "full" ]; then
            TX=$XOFF
            TY=$YOFF
        else
            case "$terminal_position" in
                top-left)     TX=$XOFF;              TY=$YOFF              ;;
                top-right)    TX=$((DW-TW+XOFF));    TY=$YOFF              ;;
                bottom-left)  TX=$XOFF;              TY=$((DH-TH+YOFF))   ;;
                bottom-right) TX=$((DW-TW+XOFF));    TY=$((DH-TH+YOFF))   ;;
                *)            TX=$(((DW-TW)/2+XOFF)); TY=$(((DH-TH)/2+YOFF)) ;;
            esac
        fi
    fi

    CLASS_NAME='mx-updater'

    XDO=""
    # Wayland check - no xdotool
    # if wayland is running, no xdotool or otehr X11 tool will work
    # we disable xdo here, with a dummy command ": "

    # - systemd is running
    if [ -d /run/systemd/system ]; then
        # - systemd is running
        # session type either "Type=wayland" or  "Type=x11"
        if  [ x"$(loginctl show-session $(echo $XDG_SESSION_ID) -p Type)" == x"Type=wayland" ]; then

            XDO=": " # noop cmd for XDO
        fi
    else
        # - no systemd , so we chweck only WAYLAND_DISPLAY env paramter
        if  [ -n "$WAYLAND_DISPLAY" ]; then
            XDO=": " # noop cmd for XDO
        fi

    fi

    # Also skip xdotool when letting the terminal manage its own geometry
    $use_own_geometry && XDO=": "

    if [ -z "$XDO" ]; then

        XSEARCH="xdotool sleep 0.2 search --onlyvisible --name '$T'"
        XSIZE="windowsize $TW $TH"
        XMOVE="windowmove $TX $TY"
        XCLASS="set_window --classname ${CLASS_NAME} --class ${CLASS_NAME}"

        XDO="$XSEARCH $XSIZE $XMOVE $XCLASS"
    fi

    CW=10 # char width - rough default
    CH=20 # char hight - rough default

    G=""
    $use_own_geometry || G="$(($TW/$CW))x$(($TH/$CH))+$TX+$TY"

    local kgeo_flags=() geo_flags=() rox_flags=() urxvt_flags=() zutty_flags=()
    if ! $use_own_geometry; then
        kgeo_flags=(-qwindowgeometry "${TW}x${TH}+$TX+$TY")
        geo_flags=(--geometry "$G")
        rox_flags=("--geometry=$G")
        urxvt_flags=(-geometry "$G")
        zutty_flags=(-geometry "$(($TW/$CW))x$(($TH/$CH))")
    fi

    SLEEP=0.3 # sleep

    C='bash -c "test -n '"'${msg}'"' && echo '"'$msg'"'; sleep 0.5;'" $XDO;"' '"${cmd}"'"'
    # test C='bash -c "test -n '"'${msg}'"' && echo '"'$msg'"'; sleep 0.5;'"echo TEST $XDO; $XDO;"' '"${cmd}"'"'
    K='bash -c "test -n '"'${msg}'"' && echo '"'$msg'"'; sleep 1; '"${cmd}"'"'

    XTE=$(readlink -e /usr/bin/x-terminal-emulator)

    # check whether the installed qterminal version is up-to-date enough
    if [ -z "${XTE##*qterminal*}" ]; then
       CUR_QTV=$(dpkg-query -f '${Version}' -W qterminal 2>/dev/null)
       MIN_QTV="1.2.0"
       # compare versions
       if dpkg --compare-versions "$CUR_QTV" lt  "$MIN_QTV"; then
            if [ -x /usr/bin/xfce4-terminal ]; then
                # use xfce4-terminal if installed
                XTE=usr/bin/xfce4-terminal
            else
                # use best alternative
                XTE=$(update-alternatives --display x-terminal-emulator | \
                    grep '^/' | cut -d ' ' -f4,1 |  grep -v qterminal | \
                    sort -k2nr  |  head -1 | cut -d ' ' -f1)
            fi
       fi
    fi

    case "$XTE" in

      *gnome-terminal.wrapper|*gnome-terminal)
            CMD="test -n '${msg}' && echo '$msg'; sleep 0.5; $XDO; $cmd"
            gnome-terminal --wait --hide-menubar "${geo_flags[@]}" --title "$T" -- bash -c "$CMD"
            ;;
      *konsole)
            if pgrep -x plasmashell >/dev/null; then
               konsole --nofork --hide-menubar "${kgeo_flags[@]}" -qwindowicon "$icon_kde" -qwindowtitle "$T" -e "$K"
            else
               konsole -e "$C"
               sleep 5
            fi
            ;;
      *lxterminal)
            lxterminal --no-remote -T "$T" -e "$C"
            ;;
      *mate-terminal|*mate-terminal.wrapper)
            mate-terminal --hide-menubar "${geo_flags[@]}" --class="${CLASS_NAME}" --role="${CLASS_NAME}" --title="$T" --sm-client-disable --disable-factory  -- sh -c "$C" 2>&1
            ;;
      *qterminal)
               qterminal "${kgeo_flags[@]}" -qwindowicon "$icon" -qwindowtitle "$T" -e "$C"
            ;;
      *roxterm)
            roxterm --hide-menubar --separate "${rox_flags[@]}" -T "$T" -e "$C" 2>/dev/null
            ;;
      *terminator)
            terminator --no-dbus --icon=""$icon -T "$T" -e "$C" 2>/dev/null
            ;;
      *urxvt)
            urxvt  "${urxvt_flags[@]}" -icon "$icon" -title "$T"  -e sh -c "echo '$msg'; sleep 1; $XDO; ${cmd}"
            ;;
      *xterm)
            xterm  -fa monaco -fs 12 -bg black -fg white  -xrm 'XTerm.vt100.allowTitleOps: false' -T "$T"  -e "$C"
            ;;
      *zutty)
            export EGL_LOG_LEVEL=fatal
            zutty -title "$T" "${zutty_flags[@]}" -e sh -c "$C"
            ;;
      *)    if [ -x /usr/bin/xfce4-terminal ]; then
                xfce4-terminal --disable-server --hide-menubar "${geo_flags[@]}"  --icon="$icon"  -T "$T" -e "$C" 2>/dev/null
            else
                x-terminal-emulator -T "$T" -e "$C"
            fi
            ;;
    esac
}

