#!/bin/bash

################################################################################
# WARNING: DO NOT EDIT THIS FILE MANUALLY!
#
# This file is automatically downloaded and managed by the egg installer.
# Any manual changes you make will be overwritten on the next update.
#
# To customize server settings, use the egg configuration variables in your
# Pelican or Pterodactyl panel instead.
################################################################################

DOWNLOADER="./hytale-downloader-linux-amd64"
AUTH_CACHE_FILE=".hytale-auth-tokens.json"

# Function to extract downloaded server files
extract_server_files() {
    echo "Extracting server files..."
    SERVER_ZIP="server.zip"

    if [ -f "$SERVER_ZIP" ]; then
        echo "Found server archive: $SERVER_ZIP"

        # Extract to current directory
        unzip -o "$SERVER_ZIP"

        if [ $? -ne 0 ]; then
            echo "Error: Failed to extract $SERVER_ZIP"
            exit 1
        fi

        echo "Extraction completed successfully."

        # Move contents from Server folder to current directory
        if [ -d "Server" ]; then
            echo "Moving server files from Server directory..."
            mv Server/* .
            rmdir Server
            echo "✓ Server files moved to root directory."
        fi

        # Clean up the zip file
        echo "Cleaning up archive file..."
        rm "$SERVER_ZIP"
        echo "✓ Archive removed."
    else
        echo "Error: Server archive not found at $SERVER_ZIP"
        exit 1
    fi
}

# Function to check if cached tokens exist
check_cached_tokens() {
    if [ -f "$AUTH_CACHE_FILE" ]; then
        # Check if jq is available
        if ! command -v jq &> /dev/null; then
            echo "Warning: jq not found, cannot use cached tokens"
            return 1
        fi

        # Validate JSON format
        if ! jq empty "$AUTH_CACHE_FILE" 2>/dev/null; then
            echo "Warning: Invalid cached token file, removing..."
            rm "$AUTH_CACHE_FILE"
            return 1
        fi

        echo "✓ Found cached authentication tokens"
        return 0
    fi
    return 1
}

# Function to load cached tokens (refresh_token + profile_uuid only)
load_cached_tokens() {
    REFRESH_TOKEN=$(jq -r '.refresh_token' "$AUTH_CACHE_FILE")
    PROFILE_UUID=$(jq -r '.profile_uuid' "$AUTH_CACHE_FILE")

    # Validate required tokens are present
    if [ -z "$REFRESH_TOKEN" ] || [ "$REFRESH_TOKEN" = "null" ] || \
       [ -z "$PROFILE_UUID" ] || [ "$PROFILE_UUID" = "null" ]; then
        echo "Error: Incomplete cached tokens, re-authenticating..."
        rm "$AUTH_CACHE_FILE"
        return 1
    fi

    echo "✓ Loaded cached refresh token + profile UUID"
    return 0
}

# Function to refresh access token using cached refresh token
refresh_access_token() {
    echo "Refreshing access token..."

    TOKEN_RESPONSE=$(curl -s -X POST "https://oauth.accounts.hytale.com/oauth2/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "client_id=hytale-server" \
      -d "grant_type=refresh_token" \
      -d "refresh_token=$REFRESH_TOKEN")

    ERROR=$(echo "$TOKEN_RESPONSE" | jq -r '.error // empty')
    if [ -n "$ERROR" ]; then
        echo "Error: Failed to refresh access token: $ERROR"
        return 1
    fi

    ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token')
    NEW_REFRESH_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.refresh_token // empty')

    if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
        echo "Error: No access token in refresh response"
        return 1
    fi

    # Update refresh token if a new one was provided
    if [ -n "$NEW_REFRESH_TOKEN" ] && [ "$NEW_REFRESH_TOKEN" != "null" ]; then
        REFRESH_TOKEN="$NEW_REFRESH_TOKEN"
    fi

    echo "✓ Access token refreshed"
    return 0
}

# Function to create a new game session
create_game_session() {
    echo "Creating game server session..."

    SESSION_RESPONSE=$(curl -s -X POST "https://sessions.hytale.com/game-session/new" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d "{\"uuid\": \"${PROFILE_UUID}\"}")

    # Validate JSON response
    if ! echo "$SESSION_RESPONSE" | jq empty 2>/dev/null; then
        echo "Error: Invalid JSON response from game session creation"
        echo "Response: $SESSION_RESPONSE"
        return 1
    fi

    # Extract session and identity tokens
    SESSION_TOKEN=$(echo "$SESSION_RESPONSE" | jq -r '.sessionToken')
    IDENTITY_TOKEN=$(echo "$SESSION_RESPONSE" | jq -r '.identityToken')

    if [ -z "$SESSION_TOKEN" ] || [ "$SESSION_TOKEN" = "null" ]; then
        echo "Error: Failed to create game server session"
        echo "Response: $SESSION_RESPONSE"
        return 1
    fi

    echo "✓ Game server session created successfully!"
    return 0
}

# Function to save authentication tokens (refresh_token + profile_uuid only)
save_auth_tokens() {
    cat > "$AUTH_CACHE_FILE" << EOF
{
  "refresh_token": "$REFRESH_TOKEN",
  "profile_uuid": "$PROFILE_UUID",
  "timestamp": $(date +%s)
}
EOF
    echo "✓ Refresh token cached for future use"
}

# Function to perform full authentication
perform_authentication() {
    echo "Obtaining authentication tokens..."

    # Step 1: Request device code
    AUTH_RESPONSE=$(curl -s -X POST "https://oauth.accounts.hytale.com/oauth2/device/auth" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "client_id=hytale-server" \
      -d "scope=openid offline auth:server")

    # Extract device_code and verification_uri_complete using jq
    DEVICE_CODE=$(echo "$AUTH_RESPONSE" | jq -r '.device_code')
    VERIFICATION_URI=$(echo "$AUTH_RESPONSE" | jq -r '.verification_uri_complete')
    POLL_INTERVAL=$(echo "$AUTH_RESPONSE" | jq -r '.interval')

    # Display authentication banner
    echo ""
    echo "╔═════════════════════════════════════════════════════════════════════════════╗"
    echo "║                       HYTALE SERVER AUTHENTICATION REQUIRED                 ║"
    echo "╠═════════════════════════════════════════════════════════════════════════════╣"
    echo "║                                                                             ║"
    echo "║  Please authenticate the server by visiting the following URL:              ║"
    echo "║                                                                             ║"
    echo "║  $VERIFICATION_URI  ║"
    echo "║                                                                             ║"
    echo "║  1. Click the link above or copy it to your browser                         ║"
    echo "║  2. Sign in with your Hytale account                                        ║"
    echo "║  3. Authorize the server                                                    ║"
    echo "║                                                                             ║"
    echo "║  Waiting for authentication...                                              ║"
    echo "║                                                                             ║"
    echo "╚═════════════════════════════════════════════════════════════════════════════╝"
    echo ""

    # Step 2: Poll for access token
    ACCESS_TOKEN=""
    while [ -z "$ACCESS_TOKEN" ]; do
        sleep $POLL_INTERVAL

        TOKEN_RESPONSE=$(curl -s -X POST "https://oauth.accounts.hytale.com/oauth2/token" \
          -H "Content-Type: application/x-www-form-urlencoded" \
          -d "client_id=hytale-server" \
          -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
          -d "device_code=$DEVICE_CODE")

        # Check if we got an error
        ERROR=$(echo "$TOKEN_RESPONSE" | jq -r '.error // empty')

        if [ "$ERROR" = "authorization_pending" ]; then
            echo "Still waiting for authentication..."
            continue
        elif [ -n "$ERROR" ]; then
            echo "Authentication error: $ERROR"
            exit 1
        else
            # Successfully authenticated
            ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.access_token')
            REFRESH_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.refresh_token')
            echo ""
            echo "✓ Authentication successful!"
            echo ""
        fi
    done

    # Fetch available game profiles
    echo "Fetching game profiles..."

    PROFILES_RESPONSE=$(curl -s -X GET "https://account-data.hytale.com/my-account/get-profiles" \
      -H "Authorization: Bearer $ACCESS_TOKEN")

    # Check if profiles list is empty
    PROFILES_COUNT=$(echo "$PROFILES_RESPONSE" | jq '.profiles | length')

    if [ "$PROFILES_COUNT" -eq 0 ]; then
        echo "Error: No game profiles found. You need to purchase Hytale to run a server."
        exit 1
    fi

    # Select profile based on GAME_PROFILE variable
    if [ -n "$GAME_PROFILE" ]; then
        # User specified a profile username, find matching UUID
        echo "Looking for profile: $GAME_PROFILE"
        PROFILE_UUID=$(echo "$PROFILES_RESPONSE" | jq -r ".profiles[] | select(.username == \"$GAME_PROFILE\") | .uuid")

        if [ -z "$PROFILE_UUID" ] || [ "$PROFILE_UUID" = "null" ]; then
            echo "Error: Profile '$GAME_PROFILE' not found."
            echo "Available profiles:"
            echo "$PROFILES_RESPONSE" | jq -r '.profiles[] | "  - \(.username)"'
            exit 1
        fi

        echo "✓ Using profile: $GAME_PROFILE (UUID: $PROFILE_UUID)"
    else
        # Use first profile from the list
        PROFILE_UUID=$(echo "$PROFILES_RESPONSE" | jq -r '.profiles[0].uuid')
        PROFILE_USERNAME=$(echo "$PROFILES_RESPONSE" | jq -r '.profiles[0].username')

        echo "✓ Using default profile: $PROFILE_USERNAME (UUID: $PROFILE_UUID)"
    fi

    echo ""

    # Save refresh token + profile for future use
    save_auth_tokens

    # Create game server session
    if ! create_game_session; then
        exit 1
    fi
    echo ""
}

# Check if the downloader exists
if [ ! -f "$DOWNLOADER" ]; then
    echo "Error: Hytale downloader not found!"
    echo "Please run the installation script first."
    exit 1
fi

# Check if the downloader is executable
if [ ! -x "$DOWNLOADER" ]; then
    echo "Setting executable permissions..."
    chmod +x "$DOWNLOADER"
fi

# Check if credentials file exists, if not run the updater
if [ ! -f ".hytale-downloader-credentials.json" ]; then
    echo "Credentials file not found, running initial setup..."
    echo "Starting Hytale downloader..."
    $DOWNLOADER -check-update
    $DOWNLOADER -patchline $PATCHLINE -download-path server.zip
    extract_server_files
fi

# Run automatic update if enabled
if [ "${AUTOMATIC_UPDATE}" = "1" ]; then
    echo "Starting Hytale downloader..."

    # Read local version from file
    if [ -f "version.txt" ]; then
        LOCAL_VERSION=$(cat version.txt)
    else
        echo "version.txt not found, forcing update"
        LOCAL_VERSION=""
    fi

    # Get remote/downloader version
    DOWNLOADER_VERSION=$($DOWNLOADER -print-version)

    echo "Local version: $LOCAL_VERSION"
    echo "Downloader version: $DOWNLOADER_VERSION"

    # Compare versions
    if [ "$LOCAL_VERSION" != "$DOWNLOADER_VERSION" ]; then
        echo "Version mismatch, running update..."

        $DOWNLOADER -check-update
        $DOWNLOADER -patchline $PATCHLINE -download-path server.zip
        extract_server_files

        # Update version.txt after successful update
        echo "$DOWNLOADER_VERSION" > version.txt
    else
        echo "Versions match, skipping update"
    fi
fi

# Check if server files were downloaded correctly
if [ ! -f "HytaleServer.jar" ]; then
    echo "Error: HytaleServer.jar not found!"
    echo "Server files were not downloaded correctly."
    exit 1
fi

# Check for cached authentication tokens
if check_cached_tokens && load_cached_tokens; then
    echo "Using cached authentication..."
    if refresh_access_token; then
        # Update cache in case refresh token rotated
        save_auth_tokens
        # Create fresh game session
        if ! create_game_session; then
            exit 1
        fi
    else
        # Refresh failed, need full re-auth
        echo "Refresh token expired, re-authenticating..."
        rm -f "$AUTH_CACHE_FILE"
        perform_authentication
    fi
else
    # Perform full authentication if no valid cache exists
    perform_authentication
fi

echo "Starting Hytale server..."

# Build the Java command
JAVA_CMD="java"

# Add AOT cache if enabled
if [ "${LEVERAGE_AHEAD_OF_TIME_CACHE}" = "1" ]; then
    JAVA_CMD="${JAVA_CMD} -XX:AOTCache=HytaleServer.aot"
fi

# Add max memory if set and greater than MEMORY_OVERHEAD
if [ -n "${SERVER_MEMORY}" ] && [ "${SERVER_MEMORY}" -gt "${MEMORY_OVERHEAD}" ] 2>/dev/null; then
    JAVA_MEMORY=$((SERVER_MEMORY - MEMORY_OVERHEAD))
    JAVA_CMD="${JAVA_CMD} -Xms${JAVA_MEMORY}M -Xmx${JAVA_MEMORY}M"
fi

# Add JVM arguments if set
if [ -n "${JVM_ARGS}" ]; then
    JAVA_CMD="${JAVA_CMD} ${JVM_ARGS}"
fi

JAVA_CMD="${JAVA_CMD} -jar HytaleServer.jar"

# Add assets parameter if set and ends with .zip
if [ -n "${ASSET_PACK}" ] && [[ "${ASSET_PACK}" == *.zip ]]; then
    JAVA_CMD="${JAVA_CMD} --assets ${ASSET_PACK}"
fi

# Add accept-early-plugins flag if variable is set
if [ "${ACCEPT_EARLY_PLUGINS}" = "1" ]; then
    JAVA_CMD="${JAVA_CMD} --accept-early-plugins"
fi

JAVA_CMD="${JAVA_CMD} --auth-mode ${AUTH_MODE}"

# Add allow-op flag if variable is set
if [ "${ALLOW_OP}" = "1" ]; then
    JAVA_CMD="${JAVA_CMD} --allow-op"
fi

# Add disable-sentry flag if enabled
if [ "${DISABLE_SENTRY}" = "1" ]; then
    JAVA_CMD="${JAVA_CMD} --disable-sentry"
fi

# Add backup parameters if enabled
if [ "${ENABLE_BACKUPS}" = "1" ]; then
    JAVA_CMD="${JAVA_CMD} --backup --backup-dir ./backup --backup-frequency ${BACKUP_FREQUENCY}"
fi

# Add session tokens and owner UUID
JAVA_CMD="${JAVA_CMD} --session-token ${SESSION_TOKEN}"
JAVA_CMD="${JAVA_CMD} --identity-token ${IDENTITY_TOKEN}"
JAVA_CMD="${JAVA_CMD} --owner-uuid ${PROFILE_UUID}"

# Add bind address
JAVA_CMD="${JAVA_CMD} --bind 0.0.0.0:${SERVER_PORT}"

# Execute the command
eval $JAVA_CMD
