#!/bin/sh -ex
#
# 01. "should check code directly not $?"
# shellcheck disable=2181
#
# 02. "can't follow . import"
# shellcheck disable=1090,1091
#
# 03. "possible misspelling"
# shellcheck disable=2153
#
# 04. "use find .. over ls"
# shellcheck disable=2011
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

# ===================================================
# 01. Attempt to load global DayZ values
# ===================================================
echo "Starting, attempting to load globals.sh"

GLOBALS_FILE="$PWD/globals.sh"
if [ -e "$GLOBALS_FILE" ] ; then
    chmod +x "$GLOBALS_FILE"
    . "$GLOBALS_FILE"
else
    >&2 echo "Could not load: $GLOBALS_FILE"
    exit 1
fi

# ===================================================
# 02. Local script variables
# ===================================================
#
#
# Local server file hierarchy:
#
#     c:/DAYZ
#         ^--/servers
#         ^--/cache
#
export ORIGINAL_DIR="$PWD"
export LOCAL_DAYZ_FILES="/mnt/c/DAYZ"
export CACHE="$LOCAL_DAYZ_FILES/cache"
export STOCK_SERVER_CACHE="$CACHE/stock_server"
export MOD_CACHE="$CACHE/mods"
export SERVERS="$LOCAL_DAYZ_FILES/servers"

# (4 hours, in seconds)
################################# export RESTART_INTERVAL=$((60 * 60 * 4))

# (10 minutes)
export RESTART_INTERVAL=$((10 * 60))

# ===================================================
# 03. Mount network drive
# ===================================================
if ! is_network_drive_mounted ; then
    mount_dayz_network_drive

    if ! is_network_drive_mounted ; then
        die "Could not mount network drive"
    fi
fi

# ===================================================
# 04. init and checks
# ===================================================
check() {
    if [ ! -d "$LOCAL_DAYZ_FILES" ] ; then
        die "dir: $LOCAL_DAYZ_FILES does not exist"
    fi
    if [ ! -d "$SERVER_HOME" ] ; then
        die "dir: $SERVER_HOME does not exist"
    fi

    msg "Health checks completed successfully."
}

init_server() {
    mkdir -p "$SERVER_HOME" "$CACHE" "$MOD_CACHE" "$STOCK_SERVER_CACHE" "$LOCAL_DAYZ_FILES/stock/maps/$MAP_FOLDER_NAME"
    :>"$SERVER_HOME/.modstring"

    check || die "Failed check()"

    msg "Completed intialization. Using server restart time of $RESTART_INTERVAL seconds."
}

# ===================================================
# 05. Load stock files
# ===================================================
load_stock_map_data() {
    mkdir -p "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME"

    do_sync --exclude='*storage_1*' \
        "$LOCAL_DAYZ_FILES/stock/maps/$MAP_FOLDER_NAME"/ \
        "$SERVER_HOME/mpmissions/$MAP_FOLDER_NAME" || \
        die "Failed to copy remote stock map data to local cache"
}

refresh_local_cache() {
    msg "Refreshing local stock server cache"
    if ! islocked_remote_server ; then
        do_sync "$REMOTE_STOCK_SERVER"/ "$STOCK_SERVER_CACHE" || die "Failed to copy remote stock server data to local cache"
    else
        msg "Remote server is locked, sleeping..."
        while islocked_remote_server ; do
            sleep 15
            echo 'Sleeping...'
        done
        do_sync "$REMOTE_STOCK_SERVER"/ "$STOCK_SERVER_CACHE" || die "Failed to copy remote stock server data to local cache"
    fi
    msg "Sucessfully copied stock server data into local cache"

    # -------------------------------------

    msg "Refreshing local map data cache for: $MAP_FOLDER_NAME"
    if ! islocked_remote_server ; then
        do_sync "$REMOTE_MAPS/$MAP_FOLDER_NAME"/ "$LOCAL_DAYZ_FILES/stock/maps/$MAP_FOLDER_NAME" || \
            die "Failed to copy remote stock map data for: $MAP_FOLDER_NAME"
    else
        msg "Remote server is locked, sleeping..."
        while islocked_remote_server ; do
            sleep 15
            echo 'Sleeping...'
        done
        do_sync "$REMOTE_MAPS/$MAP_FOLDER_NAME"/ "$LOCAL_DAYZ_FILES/stock/maps/$MAP_FOLDER_NAME" || \
            die "Failed to copy remote stock map data for: $MAP_FOLDER_NAME"
    fi
    msg "Successfully copied stock map data for: $MAP_FOLDER_NAME"

    # -------------------------------------

    msg "Refreshing local mods cache"
    if ! islocked_remote_server ; then
        do_sync "$REMOTE_MODS"/ "$MOD_CACHE" || die "Failed to copy remote mods to local cache"
    else
        msg "Remote server is locked, sleeping..."
        while islocked_remote_server ; do
            sleep 15
            echo 'Sleeping...'
        done
        do_sync "$REMOTE_MODS"/ "$MOD_CACHE" || die "Failed to copy remote mods to local cache"
    fi
    msg "Successfully copied remote mods into local cache"
}

setup_environment() {
    msg "Copying stock server data from local cache into $SERVER_HOME"
    # list of all stock server folders
    for folder in addons battleye bliss docs dta keys ; do
        do_sync "$STOCK_SERVER_CACHE/$folder"/ "$SERVER_HOME/$folder" || die "Failed to copy stock: $folder"
    done
    # list of all stock server files
    for file in dayz.gproj dayzsetting.xml whitelist.txt \
                DayZServer_x64.exe steam_api64.dll steamclient64.dll \
                tier0_s64.dll vstdlib_s64.dll ; do
        cp -fv "$STOCK_SERVER_CACHE/$file" "$SERVER_HOME/$file" || die "Failed to copy stock: $file"
    done

    msg "Copying into $SERVER_HOME stock map data for: $MAP_FOLDER_NAME"
    load_stock_map_data

    msg "Copying mod files from local cache into $SERVER_HOME"
    do_sync "$MOD_CACHE/$MAP_FOLDER_NAME"/ "$SERVER_HOME/mods" || die "Failed to copy mods to $SERVER_HOME"

    msg "Copying DZSA executable"
    do_sync "$REMOTE_DIR/res/software/DZSALModServer.exe" "$SERVER_HOME"/ || die "Failed to copy DZSALModServer.exe"
}

# finds list of mods to load and stores them in .modstring file
# to be used as parameters to the server
load_mods() {
    if [ ! -f "$MOD_CACHE/$MAP_FOLDER_NAME/mods.txt" ] ; then
        die "mods.txt list for $MAP_FOLDER_NAME is missing"
    fi

    mkdir -p "$SERVER_HOME/mods"

    _modstring=""
    while read -r mod ; do
        case $mod in
            '@'*)
                msg "- Found mod: $mod"
                _modstring="$_modstring;mods/$mod"

                # common spelling differences, check for all
                for addon_folder in addons Addons addon Addon add_ons add_on Add_on Add_ons ; do
                    if [ -d "$SERVER_HOME/mods/$mod/$addon_folder" ] ; then
                        for addon in "$SERVER_HOME/mods/$mod/$addon_folder"/* ; do
                            if [ ! -f "$SERVER_HOME/addons/${addon##*/}" ] ; then
                                cp -f "$addon" "$SERVER_HOME/addons/"
                            fi
                        done
                    fi
                done

                for key_folder in keys Keys key Key ; do
                    if [ -d "$SERVER_HOME/mods/$mod/$key_folder" ] ; then
                        for key in "$SERVER_HOME/mods/$mod/$key_folder"/* ; do
                            if [ ! -f "$SERVER_HOME/keys/${key##*/}" ] ; then
                                cp -f "$key" "$SERVER_HOME/keys/"
                            fi
                        done
                    fi
                done
        esac
    done < "$MOD_CACHE/$MAP_FOLDER_NAME/mods.txt"

    # trim the initial leading ';'
    _modstring=${_modstring#;}
    printf '%s\n' "$_modstring" > .modstring
    unset _modstring

    msg "Mods successfully loaded. Using modstring:"
    printf '"%s"\n' "$(cat .modstring)"
}

# ===================================================
# 06. Start function
# ===================================================
start_server() {
    check || die "Failed check()"

    # wait until dayz-modserver lockfile is released on the NAS
    if islocked_remote_server ; then
        msg "Remote file server is currently locked"
        msg "Sleeping until is no longer locked..."
        while islocked_remote_server ; do
            echo "Sleeping..."
            sleep 10
        done
        msg "Server unlocked! Continuing..."
    fi

    cd "$SERVER_HOME" || die "Could not cd to '$SERVER_HOME'"

    msg "Setting up environment"
    setup_environment || die "Could not set up environment."

    msg "Loading mods"
    load_mods || die "Could not load mods"
    mod_string=$(cat .modstring)

# =====================================================================================
# creating temp.bat here to avoid the arg max char limit of windows cmd.exe
cat > temp.bat <<EOF
:start
start "$SERVER_NAME" /min DZSALModServer.exe -config=serverDZ.cfg -port="$SERVER_PORT" -profiles=Profilesfolder -mod="$mod_string" -cpuCount="$SERVER_CPU" -dologs -adminlog -netlog -freezecheck
EOF
# =====================================================================================

    # start the server
    cmd.exe /C temp.bat

    echo '===================================='
    printf '%s - Server started.\n' "$(date)"
    echo '===================================='

    printf '\n**** Sleeping for: %s *****\n\n' "$RESTART_INTERVAL"

    count=0
    while [ "$count" -lt "$RESTART_INTERVAL" ] ; do
        sleep 60
        count=$((count + 60))
        msg "TIME LEFT BEFORE RESTART: $(( (RESTART_INTERVAL - count) / 60 )) minutes"
    done

    echo "==========================="

    msg "Time up"
    msg "Killing server"
    cmd.exe /C taskkill /im DayZServer_x64.exe /F
    rm -f temp.bat 2>/dev/null ||:

    msg "Sleeping 10 seconds to settle"
    sleep 10
    msg "SERVER IS RESTARTING"

}

# ===================================================
# 07. Main loop
# ===================================================
main() {
    cd "$ORIGINAL_DIR" || die "Can no longer cd to $ORIGINAL_DIR"

    if [ -e ./SERVER.ENV ] ; then
        . ./SERVER.ENV
    else
        die "Could not source ./SERVER.ENV"
    fi

    # this must be here and not up top as we must load it from the SERVER.ENV
    export SERVER_HOME="$SERVERS/$SERVER_NAME"

    # create directories in $SERVER_HOME
    # blank the modstring
    init_server

    if [ -e ./serverDZ.cfg ] ; then
        cp -f ./serverDZ.cfg "$SERVER_HOME"/ || die "Failed to copy ./serverDZ into $SERVER_HOME"
    else
        die "Could not find ./serverDZ.cfg"
    fi

    # sync remote server stock and mod files into local cache
    refresh_local_cache || die "Failed to refresh local cache."

    # load stock server, map, mod files into $SERVER_HOME
    setup_environment || die "Failed to setup environment."

    # START THE SERVER - RUN ServerDZ.EXE
    start_server "$@"
}

main "$@" || exit 1
