#!/bin/bash

ini_set_key() {
    local file="$1"
    local section="$2"
    local key="$3"
    local value="$4"
    local tmp

    tmp="${file}.tmp.$$"

    awk -v section="$section" -v key="$key" -v value="$value" '
    BEGIN {
        in_section = 0
        section_found = 0
        key_done = 0
    }

    function flush_missing_key() {
        if (in_section && !key_done) {
            print key "=" value
            key_done = 1
        }
    }

    /^\[[^]]+\]$/ {
        if (in_section) {
            flush_missing_key()
            in_section = 0
        }

        if ($0 == "[" section "]") {
            in_section = 1
            section_found = 1
        }

        print
        next
    }

    {
        if (in_section && $0 ~ ("^" key "=")) {
            if (!key_done) {
                print key "=" value
                key_done = 1
            }
            next
        }

        print
    }

    END {
        if (in_section) {
            flush_missing_key()
        }

        if (!section_found) {
            print "[" section "]"
            print key "=" value
        }
    }' "$file" > "$tmp" && mv "$tmp" "$file"
}

ini_del_key() {
    local file="$1"
    local section="$2"
    local key="$3"
    local tmp

    tmp="${file}.tmp.$$"

    awk -v section="$section" -v key="$key" '
    BEGIN {
        in_section = 0
    }

    /^\[[^]]+\]$/ {
        in_section = ($0 == "[" section "]")
        print
        next
    }

    {
        if (in_section && $0 ~ ("^" key "=")) {
            next
        }
        print
    }' "$file" > "$tmp" && mv "$tmp" "$file"
}

GAME_BINARY="ut-bin"
SYSTEM_DIR="System"

# Additional commandline options for mods etc.
CMD_ARGS=()

# don't use US keyboard layout
#NOUSLAYOUT="true"

resolve_link() {
    local path target dir
    path="$1"

    [ -L "$path" ] || return 1

    target="$(LC_ALL=C ls -l "$path" 2>/dev/null)"
    target="${target##* -> }"

    case "$target" in
        /*) printf '%s\n' "$target" ;;
        *)
            dir="$(dirname "$path")"
            printf '%s\n' "$dir/$target"
            ;;
    esac
}

LANG=POSIX
export LANG
script="$0"
count=0
while [ -L "$script" ]
do
    script="$(resolve_link "$script")"
    count=$((count + 1))
    if [ "$count" -gt 100 ]
    then
        echo "Too many symbolic links"
        exit 1
    fi
done

GAME_DIR="$(cd "$(dirname "$script")" && pwd)"
GAME_SYSTEM_DIR="${GAME_DIR}/${SYSTEM_DIR}"
USER_UT_DIR="${HOME}/.loki/ut/${SYSTEM_DIR}"
SYSTEM_DEFAULT_GLIDE="${GAME_SYSTEM_DIR}/Default-glide.ini"
SYSTEM_DEFAULT_OPENGL="${GAME_SYSTEM_DIR}/Default-opengl.ini"
SYSTEM_DEFAULT_USER="${GAME_SYSTEM_DIR}/DefUser.ini"
USER_UT_INI="${USER_UT_DIR}/UnrealTournament.ini"
USER_USER_INI="${USER_UT_DIR}/User.ini"

if [ ! -d "${USER_UT_DIR}" ]
then
    mkdir -p "${USER_UT_DIR}"
fi

detect_renderer() {
    if [ -e /usr/lib/libglide2x.so ] || [ -e /usr/local/lib/libglide2x.so ]; then
        echo "glide"
    else
        echo "opengl"
    fi
}

install_ini_profile() {
    local renderer="$1"

    case "$renderer" in
        glide)
            if [ -r "${SYSTEM_DEFAULT_GLIDE}" ]; then
                cp -f "${SYSTEM_DEFAULT_GLIDE}" "${USER_UT_INI}"
                return 0
            fi
            ;;
        opengl)
            if [ -r "${SYSTEM_DEFAULT_OPENGL}" ]; then
                cp -f "${SYSTEM_DEFAULT_OPENGL}" "${USER_UT_INI}"
                return 0
            fi
            ;;
    esac

    return 1
}

if [ ! -f "${USER_UT_INI}" ]; then
    RENDERER="$(detect_renderer)"
    install_ini_profile "${RENDERER}" || {
        echo "Failed to install renderer profile: ${RENDERER}"
        exit 1
    }
    ini_set_key "${USER_UT_INI}" "Engine.Engine" "AudioDevice" "Audio.GenericAudioSubsystem"
    ini_set_key "${USER_UT_INI}" "Core.System" "CacheSizeMegs" "32"
    ini_set_key "${USER_UT_INI}" "WinDrv.WindowsClient" "FullscreenViewportX" "800"
    ini_set_key "${USER_UT_INI}" "WinDrv.WindowsClient" "FullscreenViewportY" "600"
    ini_set_key "${USER_UT_INI}" "Audio.GenericAudioSubsystem" "UseSpatial" "True"
    ini_set_key "${USER_UT_INI}" "Audio.GenericAudioSubsystem" "UseReverb" "True"
    ini_set_key "${USER_UT_INI}" "Audio.GenericAudioSubsystem" "OutputRate" "44100Hz"
    ini_set_key "${USER_UT_INI}" "IpDrv.TcpNetDriver" "ConfiguredInternetSpeed" "25000"

    if ! grep -q '^\[UBrowser\.UBrowserFavoritesFact\]$' "${USER_UT_INI}"; then
        printf '%s\n' \
            '[UBrowser.UBrowserFavoritesFact]' \
            'FavoriteCount=1' \
            'Favorites[0]=Vogons\5.196.92.222\5091\False' \
            >> "${USER_UT_INI}"
    fi

fi

# Remove passwords from UnrealTournament.ini
if [ -r "${USER_UT_INI}" ]
then
    sed -i \
        -e 's/^\(SavedPasswords\[[0-9]*\]=\).*/\1/' \
        -e 's/^\(PasswordHistory\[[0-9]*\]=\).*/\1/' \
        "${USER_UT_INI}"
fi


set_random_ut_name() {
    local target_file="$1"

    [ -n "$target_file" ] || return 1
    [ -f "$target_file" ] || return 1

    local names='
Phobos
Vortex
Raptor
Hexer
Cobra
Grendel
Nyx
Blitz
Talon
Havoc
Stryker
Wraith
Nova
Reaper
Goliath
Drift
Razor
Pixel
Onyx
Fury
'

    local count=$(printf '%s\n' "$names" | sed '/^$/d' | wc -l)
    local idx=$(( (RANDOM % count) + 1 ))
    local base_name=$(printf '%s\n' "$names" | sed '/^$/d' | sed -n "${idx}p")
    local suffix=$(printf '%02d' $((RANDOM % 100)))
    local new_name="${base_name}${suffix}"

    sed -i "s/^Name=Player$/Name=${new_name}/" "$target_file"
}

if [ ! -f "${USER_USER_INI}" ]; then
    if [ ! -r "${SYSTEM_DEFAULT_USER}" ]; then
        echo "Missing ${SYSTEM_DEFAULT_USER}"
        exit 1
    fi
    cp -f "${SYSTEM_DEFAULT_USER}" "${USER_USER_INI}"
    set_random_ut_name "${USER_USER_INI}"

    ini_del_key "${USER_USER_INI}" "Engine.Input" "Left"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "Up"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "Right"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "Down"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "Z"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "Q"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "S"
    ini_del_key "${USER_USER_INI}" "Engine.Input" "D"
    ini_del_key "${USER_USER_INI}" "Engine.PlayerPawn" "DodgeClickTime"

    ini_set_key "${USER_USER_INI}" "Engine.Input" "W" "MoveForward"
    ini_set_key "${USER_USER_INI}" "Engine.Input" "A" "StrafeLeft"
    ini_set_key "${USER_USER_INI}" "Engine.Input" "S" "MoveBackward"
    ini_set_key "${USER_USER_INI}" "Engine.Input" "D" "StrafeRight"
    ini_set_key "${USER_USER_INI}" "Engine.PlayerPawn" "0.250000"
    
fi

# games run better with US keyboard layout
restore_xkb() {
    [ -n "$OLD_XKB_LAYOUT" ] && setxkbmap "$OLD_XKB_LAYOUT" >/dev/null 2>&1 || true
}

OLD_XKB_LAYOUT="$(setxkbmap -query 2>/dev/null | awk '$1=="layout:" {print $2}')"
trap restore_xkb EXIT
setxkbmap us >/dev/null 2>&1 || true

LD_LIBRARY_PATH="${GAME_SYSTEM_DIR}:${LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH

cd "${GAME_SYSTEM_DIR}" || exit 1

# start the game
if nice -n -5 true >/dev/null 2>&1; then
    echo "Launching UT99 with elevated priority"
    exec nice -n -5 -- "./$GAME_BINARY" "${CMD_ARGS[@]}" "$@"
else
    echo "Negative nice not permitted, launching normally"
    exec "./$GAME_BINARY" "${CMD_ARGS[@]}" "$@"
fi
