#!/usr/bin/env bash

RED="\033[1;91m"
BLUE="\033[1;94m"
GREEN="\033[1;92m"
YELLOW="\033[1;33m"
RESETCOLOR="\033[1;00m"

print_error () { echo -e "${RED}[ ERROR ][$(date +"%Y.%m.%d %T")]: $* $RESETCOLOR" ; }

print_info () { echo -e "${GREEN}[ INFO ][$(date +"%Y.%m.%d %T")]: $* $RESETCOLOR" ; }

print_warning () { echo -e "${YELLOW}[ WARNING ][$(date +"%Y.%m.%d %T")]: $* $RESETCOLOR" ; }

if [ "${EUID}" == 0 ]; then
    clear
    print_error "Please do not run this script as root!"
    exit 1
fi

#    version
export SW_GIT_VER="421"
export SW_RUNTIME_GIT_VER="14"

[ ! -d "${HOME}/.config" ] && \
    mkdir -p "${HOME}/.config"

[ ! -d "${HOME}/.local/bin" ] && \
    mkdir -p "${HOME}/.local/bin"

[ ! -d "${HOME}/.local/share/applications" ] && \
    mkdir -p "${HOME}/.local/share/applications"

if [ -f "${HOME}/.config/swrc" ]; then
    START_WINE_PATH="$(cat "${HOME}/.config/swrc"|head -n1)"
    export START_WINE_PATH
else
    START_WINE_PATH="${HOME}/.local/share/StartWine"
    export START_WINE_PATH
fi

[ -n "$(tty|grep -v 'not a'|grep -Eo 'tty|pts')" ] && \
    export SW_SILENT_DL=1

export SW_RUNTIME="${START_WINE_PATH}/data/runtime/sw_runtime"

[ -d "${START_WINE_PATH}" ] && \
    export DIRECTORY_EXIST="true"

[ ! -d "${START_WINE_PATH}/data/tmp" ] && \
    mkdir -p "${START_WINE_PATH}/data/tmp"

if [ -f "${START_WINE_PATH}/data/runtime/version" ]; then
    SW_RUNTIME_CURRENT_VER="$(cat "${START_WINE_PATH}/data/runtime/version")"
    export SW_RUNTIME_CURRENT_VER
fi

if [ -f "${START_WINE_PATH}/data/scripts/version" ]; then
    SW_CURRENT_VER="$(cat "${START_WINE_PATH}/data/scripts/version")"
    export SW_CURRENT_VER
fi

sw_check_url () {

    timeout=3
    tmp_file=$(mktemp)
    URL_DOWNLOAD=""

    check_speed() {
        export url=$1

        res=$(curl -r 0-10485760 -L -s -m $timeout -o /dev/null -w "%{http_code} %{speed_download}" "$url" 2>/dev/null)
        status=$(echo $res | cut -d' ' -f1)
        speed=$(echo $res | cut -d' ' -f2 | cut -d'.' -f1)

        if [[ "$status" =~ ^2[0-9]{2}$ ]]; then
            speed_mb=$(awk -v s="$speed" 'BEGIN {printf "%.2f", s / 1048576}')
            print_info "URL: ${url:0:40}... | STATUS: $status | SPEED: $speed_mb MB/s"
            echo "$speed $url" >> "$tmp_file"
        else
            print_error "URL: ${url:0:40}... | STATUS: $status | SKIP (ERROR: or Unavailable)"
        fi
    }

    for url in "${FTP_URL[@]}"; do
        check_speed "$url" &
    done

    wait

    if [ -s "$tmp_file" ]; then
        best_result=$(sort -rn "$tmp_file" | head -n 1)
        URL_DOWNLOAD=$(echo "$best_result" | cut -d' ' -f2-)
        echo "---------------------------------------"
        print_info "Fastest available URL: $URL_DOWNLOAD"
    else
        echo "---------------------------------------"
        print_error "None of the servers are accessible."
    fi

    rm -f "$tmp_file"

}

try_download () {

    if [ ! -n "$(tty|grep -v 'not a'|grep -Eo 'tty|pts')" ]; then
        export NOT_TERM=1
    else
        export NOT_TERM=0
    fi

    is_exist () { command -v "$@" &>/dev/null ; }

    err_no_downloader () {

        error_msg "Downloader not found!"
        exit 1

    }

    check_url_stat_code () {

        if is_exist curl ; then
            curl -sL -o /dev/null -I -w "%{http_code}" "$@" 2>/dev/null
        elif is_exist wget ; then
            wget --no-check-certificate --server-response \
            --spider "$@"|& awk '/^  HTTP/{print$2}'|tail -1
        else
            return 1
        fi

    }

    is_url () {

        [ ! -n "$1" ] && \
            return 1

        if [ -n "$2" ]; then
            [ "$(check_url_stat_code "$1")" == "$2" ]
        else
            [ "$(check_url_stat_code "$1")" == "200" ]
        fi

    }

    yn_case () {

        while true ; do
            read -p "$(echo -e "${RED}$1 ${GREEN}(y/n) ${BLUE}> $RESETCOLOR")" yn
            case $yn in
                [Yy] ) return 0 ;;
                [Nn] ) return 1 ;;
            esac
        done

    }

    error_msg () {

        echo -e "${RED}[ ERROR ][$(date +"%Y.%m.%d %T")]: $@ $RESETCOLOR"
        if [ "$NOT_TERM" == 1 ]; then
            notify-send -a 'StartWine Error' "$@" 2>/dev/null &
        fi

    }

    rm_fail_dl () {

        [ -f "$FILEDIR/$FILENAME" ] && \
            rm -rf "$FILEDIR/$FILENAME" \
            "$FILEDIR/$FILENAME"*.aria2

    }

    dl_ret () {

        if [ "$1" != 0 ]; then
            rm_fail_dl
            dl_repeat && try_download "$URL" "$FILEDIR/$FILENAME" || return 1
        else
            return 0
        fi

    }

    dl_repeat () {

        DL_REP_TITLE="Download interrupted!"
        DL_REP_TEXT="Failed to download: $FILENAME from $(echo "$URL"|awk -F/ '{print$3"/"$4}') \nWould you like to repeat it?"

        if [ "$NOT_TERM" != 1 ]; then
            yn_case "$DL_REP_TEXT"||return 1
        elif is_exist yad ; then
            yad --image="dialog-error" --button="CANCEL:1" --center \
            --button="REPEAT:0" --title="$DL_REP_TITLE" \
            --text="$DL_REP_TEXT" --on-top --fixed
        elif is_exist zenity ; then
            zenity --question --title="$DL_REP_TITLE" --no-wrap \
            --text="$DL_REP_TEXT"
        else
            return 1
        fi

    }

    if [ -n "$1" ]; then
        URL="$1"

        if [ -n "$2" ]; then
            if [ -d "$2" ]; then
                FILEDIR="$2"
                FILENAME="$(basename "$1")"
            else
                FILEDIR="$(dirname "$2")"
                FILENAME="$(basename "$2")"
            fi
        else
            FILEDIR="."
            FILENAME="$(basename "$1")"
        fi

        if is_url "$URL" ; then
            WGET_ARGS=(--no-check-certificate --content-disposition -t 3 -T 5 -w 0.5 "$URL" -O "$FILEDIR/$FILENAME")
            [ ! -d "$FILEDIR" ] && \
                mkdir -p "$FILEDIR"

            if [ "$NOT_TERM" == 1 ] && (is_exist yad||is_exist zenity) ; then
                set -o pipefail

                dl_progress () {

                    [[ "$URL" =~ '&key=' ]] && \
                        local URL="$(echo "$URL"|sed "s|\&key=.*||g")"
                    [[ "$URL" =~ '&' && ! "$URL" =~ '&amp;' ]] && \
                        local URL="$(echo "$URL"|sed "s|\&|\&amp;|g")"
                    if is_exist yad ; then
                        yad --progress --percentage=0 --text="Download:\t$FILENAME\n$URL" \
                        --auto-close --no-escape --selectable-labels --auto-kill \
                        --center --on-top --fixed --no-buttons --undecorated --skip-taskbar
                    elif is_exist zenity ; then
                        zenity --progress --text="Connecting to $URL" --width=650 --height=40 \
                        --auto-close --no-cancel --title="Download: $FILENAME"
                    else
                        return 1
                    fi

                }

                dl_progress_pulsate () {

                    local ret=1
                    [[ "$URL" =~ '&key=' ]] && \
                        local URL="$(echo "$URL"|sed "s|\&key=.*||g")"
                    [[ "$URL" =~ '&' && ! "$URL" =~ '&amp;' ]] && \
                        local URL="$(echo "$URL"|sed "s|\&|\&amp;|g")"

                    if is_exist yad ; then
                        local yad_args=(
                            --progress --pulsate --text="Download:\t$FILENAME\n$URL"
                            --width=650 --height=40 --undecorated --skip-taskbar
                            --no-buttons --text-align center --auto-close --auto-kill
                            --center --fixed --on-top --no-escape --selectable-labels
                        )
                        "$@" &
                        local exec_pid="$!"

                        if [[ -n "$exec_pid" && -d "/proc/$exec_pid" ]]; then
                            (while [ -d "/proc/$exec_pid" ]
                                do echo -e "#\n" ; sleep 0.1 2>/dev/null
                            done)|yad "${yad_args[@]}" &>/dev/null &
                            local yad_pid="$!"
                            wait "$exec_pid" &>/dev/null
                            ret="$?"
                            kill "$yad_pid" &>/dev/null
                        fi

                    elif is_exist zenity ; then
                        "$@"|zenity --progress --pulsate --text="$URL" --width=650 --height=40 \
                        --auto-close --no-cancel --title="Download: $FILENAME"
                        ret="$?"
                    fi

                    return "$ret"

                }

                if is_exist aria2c ; then
                    aria2c --no-conf -R -x 13 -s 13 --allow-overwrite --summary-interval=1 -o \
                    "$FILENAME" -d "$FILEDIR" "$URL"|grep --line-buffered 'ETA'|\
                    sed -u 's|(.*)| &|g;s|(||g;s|)||g;s|\[||g;s|\]||g'|\
                    awk '{print$3"\n#Downloading at "$3,$2,$5,$6;system("")}'|\
                    dl_progress
                elif is_exist curl ; then
                    curl -R --progress-bar --insecure --fail -L "$URL" -o \
                    "$FILEDIR/$FILENAME" |& tr '\r' '\n'|sed '0,/100/{/100/d;}'|\
                    sed -ur 's|[# ]+||g;s|.*=.*||g;s|.*|#Downloading at &\n&|g'|\
                    dl_progress
                elif is_exist wget2 ; then
                    dl_progress_pulsate wget2 "${WGET_ARGS[@]}"
                elif is_exist wget ; then
                    wget "${WGET_ARGS[@]}"|& tr '\r' '\n'|\
                    sed -u 's/.* \([0-9]\+%\)\ \+\([0-9,.]\+.\) \(.*\)/\1\n#Downloading at \1\ ETA: \3/; s/^20[0-9][0-9].*/#Done./'|\
                    dl_progress
                else
                    err_no_downloader
                fi

                dl_ret "${PIPESTATUS[0]}"||return 1
            else
                if is_exist aria2c ; then
                    aria2c --no-conf -R -x 13 -s 13 --allow-overwrite -d "$FILEDIR" -o "$FILENAME" "$URL"
                elif is_exist curl ; then
                    curl -R --progress-bar --insecure --fail -L "$URL" -o "$FILEDIR/$FILENAME"
                elif is_exist wget2 ; then
                    wget2 -q --force-progress "${WGET_ARGS[@]}"
                elif is_exist wget ; then
                    wget -q --show-progress "${WGET_ARGS[@]}"
                else
                    err_no_downloader
                fi

                dl_ret "$?"||return 1
            fi
        else
            error_msg "$FILENAME not found in $(echo "$URL"|awk -F/ '{print$3"/"$4}')"
            return 1
        fi
    else
        error_msg "Specify download URL!"
        return 1
    fi

}

if [[ "${SW_RUNTIME_CURRENT_VER}" -lt "${SW_RUNTIME_GIT_VER}" ]]; then

    [ -f "${SW_RUNTIME}" ] && \
        rm -rf "${SW_RUNTIME}"

    [ ! -d "${START_WINE_PATH}/data/runtime" ] && \
        mkdir -p "${START_WINE_PATH}/data/runtime"

    export FTP_URL=(
        "https://startwine-launcher.ru/StartWine-data/runtime/sw_runtime.iso"
        "https://huggingface.co/StartWine/sw_repo/resolve/main/runtime/sw_runtime.iso?download=true"
        "https://github.com/RusNor/sw_runtime/releases/download/sw_runtime/sw_runtime.iso"
    )

    sw_check_url

    if try_download "${URL_DOWNLOAD}" "${SW_RUNTIME}"; then

        chmod +x "${SW_RUNTIME}"

        [ ! -L "${START_WINE_PATH}/data/runtime/sw" ] && \
            ln -sfr "${SW_RUNTIME}" "${START_WINE_PATH}/data/runtime/sw"

        echo "${SW_RUNTIME_GIT_VER}" > "${START_WINE_PATH}/data/runtime/version"
        print_info "Download completed successfully"
    else
        print_error "Failed to download sw_runtime from (repo), please run the installation again."
        exit 1
    fi

fi

if [[ "${SW_CURRENT_VER}" -lt "${SW_GIT_VER}" ]]; then

    [ -L "$HOME/.local/bin/sw" ] && \
        rm "$HOME/.local/bin/sw"

    [ -f "${HOME}/.cache/sw_fm/exe_data.json" ] && \
        rm -rf "${HOME}/.cache/sw_fm/exe_data.json"

    [ -d "${START_WINE_PATH}/data/tools/utils" ] && \
        rm -rf "${START_WINE_PATH}/data/tools/utils"

    [ -f "${START_WINE_PATH}/data/pfx_backup/pfx_default.iso" ] && \
        rm -rf "${START_WINE_PATH}/data/pfx_backup/pfx_default.iso"

    [ -f "${HOME}/.local/share/applications/StartWine.desktop" ] && \
        rm -rf "${HOME}/.local/share/applications/StartWine.desktop"

    [ -f "${HOME}/.local/share/applications/StartWineShell.desktop" ] && \
        rm -rf "${HOME}/.local/share/applications/StartWineShell.desktop"

    [ -f "${HOME}/.local/share/applications/StartWine.desktop" ] && \
        rm -rf "${HOME}/.local/share/applications/StartWine.desktop"

    if [ -f "/usr/share/applications/StartWine.desktop" ]; then
        cp -f "/usr/share/applications/StartWine.desktop" && \
        "${HOME}/.local/share/applications"
    fi

    if [ -f "${SW_RUNTIME}" ]; then

        export FTP_URL=(
           "https://startwine-launcher.ru/StartWine-data/releases/StartWine_v${SW_GIT_VER}.tar.xz"
           "https://huggingface.co/StartWine/sw_repo/resolve/main/release/StartWine_v${SW_GIT_VER}.tar.xz?download=true"
           "https://github.com/RusNor/StartWine-Launcher/releases/download/StartWine_v${SW_GIT_VER}/StartWine_v${SW_GIT_VER}.tar.xz"
        )

        sw_check_url

        if try_download "${URL_DOWNLOAD}" "${START_WINE_PATH}/data/tmp/StartWine_v${SW_GIT_VER}.tar.xz"; then
            print_info "Download completed successfully"
            START_WINE_EXTRACT="$(dirname "${START_WINE_PATH}")"
            export START_WINE_EXTRACT

            if [ "${DIRECTORY_EXIST}" == "true" ]; then
                "${START_WINE_PATH}/data/runtime/sw" --shutdown
                "${START_WINE_PATH}/data/runtime/sw_runtime" rim-kill all
            fi

            if "${SW_RUNTIME}" tar -xvJf "${START_WINE_PATH}/data/tmp/StartWine_v${SW_GIT_VER}.tar.xz" -C "${START_WINE_EXTRACT}"; then
                print_info "Unpacking completed successfully"
                echo "${SW_GIT_VER}" > "${START_WINE_PATH}/data/scripts/version"
                cp -rf /usr/share/startwine/data "${START_WINE_EXTRACT}/StartWine"
            else
                print_error "Failed to unpack archive"
            fi

        else
            print_error "Failed to download archive from (repo), please run the installation again..."
            exit 1
        fi

        if [ "${DIRECTORY_EXIST}" == "true" ]; then
            "${START_WINE_PATH}/data/runtime/sw_runtime" "${START_WINE_PATH}/data/scripts/sw_runlib"
            print_info "StartWine update to version ${SW_GIT_VER} completed successfully"
        else
            "${START_WINE_PATH}/data/runtime/sw" --path "${START_WINE_PATH}" "$@" 2>/dev/null

            START_WINE_PATH="$(cat "${HOME}/.config/swrc"|head -n1)"
            export START_WINE_PATH

            "${START_WINE_PATH}/data/runtime/sw_runtime" "${START_WINE_PATH}/data/scripts/sw_runlib"
            print_info "Installation completed successfully"
        fi

        exit 0
    else
        print_error "${SW_RUNTIME} not exists!"
        exit 1
    fi
else
    "${START_WINE_PATH}/data/runtime/sw" "$@"
    exit 0
fi

