#!/bin/bash

# shellcheck source=start-utils
. "$(dirname "$0")/start-utils"

# Define setup functions
function getGTNHdownloadPath(){
  gtnh_download_path=""
  local release_object=""
  local current_java_version=""
  current_java_version=$(mc-image-helper java-release)

  # Select release JSON object
  if [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then
    if ! release_object="$(
      curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
        | jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Beta release"))|.[-1]'
      )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
      exit 1
    fi
    log "Selected $(jq '.key' <<< "$release_object") as latest dev version for download."
  
  elif [ "$GTNH_PACK_VERSION" == "latest" ]; then
    if ! release_object="$(
      curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
        | jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Stable release"))|.[-1]'
      )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
      exit 1
    fi
    log "Selected $(jq '.key' <<< "$release_object") as latest version for download."
  
  else
    if ! release_object="$(
      curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
        | jq -r --arg USRIN "$GTNH_PACK_VERSION" '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.key==$USRIN))|.[]'
      )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
      exit 1
    fi
    log "Selected $(jq -r '.key' <<< "$release_object") as matching version for download."
  
  fi

  if [[ -z $release_object ]]; then
    logError "No release found for GTNH_PACK_VERSION=$GTNH_PACK_VERSION. Please check if the version is valid."
    exit 1
  fi
  
  # Select compatible server files for java version
  if (( current_java_version == 8 )); then
    gtnh_download_path=$(jq -r '.value.server.java8Url' <<< "$release_object")
    log "Use GTNH Server Java 8 release."
  
  elif (( current_java_version >= 17 )); then
    if (( current_java_version > $(jq '.value.maxJavaVersion' <<< "$release_object") )); then
      logError "Container Java version $current_java_version is not supported by GTNH. Try an older release."
      exit 1
    fi
  
    gtnh_download_path=$(jq -r '.value.server.java17_2XUrl' <<< "$release_object")
    log "Use GTNH Server Java 17+ release."
  
  else
    logError "Container Java version $current_java_version is not supported by GTNH."
    exit 1
  
  fi
  
  if [[ -z $gtnh_download_path ]]; then
    logError "Server files not found! Please check if the selected GTNH_PACK_VERSION=$GTNH_PACK_VERSION is valid."
    exit 1
  fi
  debug "Download source URL: $gtnh_download_path"

}

function deleteGTNHbackup(){
  log "Start deleting all config backups"
  if ! find . -maxdepth 1 -type d -name 'gtnh-upgrade-*' -exec rm -rf {} + ; then
    logWarning "Can not delete config backup!"
  fi
}

function downloadGTNH(){
  local gtnh_download=""
  base_dir=/data/.tmp/gtnh_base

  debug "Creating temporary /data/.tmp/packs folder for GTNH download"
  mkdir -p /data/.tmp/packs
  trap 'rm -rf /data/.tmp' EXIT
  
  log "Downloading $gtnh_download_path."
  if ! gtnh_download=$(mc-image-helper get -o /data/.tmp/packs --output-filename --skip-up-to-date "$gtnh_download_path"); then
    logError "Failed to download $gtnh_download_path"
    exit 1
  fi
  debug "Downloaded GTNH server files to $gtnh_download"

  # Unpacking Server files into temporary directory
  log "Unpacking Server Files into $base_dir"
  mkdir -p "${base_dir}"
  extract "${gtnh_download}" "${base_dir}"

  # Remove any eula file since container manages it
  debug "Removing eula.txt from $base_dir"
  rm -f "${base_dir}/eula.txt"

  # recalculate the actual base directory of content
  if ! base_dir=$(mc-image-helper find \
      --max-depth=3 --type=directory --name=mods,config \
      --only-shallowest --fail-no-matches --format '%h' \
      "$base_dir"); then
    logError "Unable to find content base of downloaded Server Files"
    exit 1
  fi
  debug "Base directory of unpacked Server Files: $base_dir"
}

function updateGTNHresource(){
  local resource="$1"
  local new_resource="$2"
  log "Trying to update $resource"

  if [[ -z "$resource" ]]; then
    logWarning "No resource specified for update"
    return 0
  fi

  if [[ -e "$resource" ]]; then
    log "Deleting existing resource: $resource"
    if ! rm -rf "$resource"; then
      logError "Failed to delete resource: $resource"
      exit 1
    fi
  fi

  if [[ -d "$new_resource" ]]; then
    log "Copying $new_resource to /data"
    if ! cp -r "$new_resource" "/data/"; then
      logError "Failed to copy $new_resource to /data"
      exit 1
    fi
    return 0
  fi
  if [[ -f "$new_resource" ]]; then
    log "Copying $new_resource to /data"
    if ! cp "$new_resource" "/data/"; then
      logError "Failed to copy $new_resource to /data"
      exit 1
    fi
    return 0
  fi

  logWarning "Resource update failed: $new_resource does not exist!"
  return 0
}

function updateGTNH(){
  # Get the current date and time
  local current_datetime=""
  current_datetime=$(date +%Y-%m-%dT+%H%M)
  
  # Define folders and files to update
  # base_dir is already defined in handleGTNH function
  local folders_to_update=("libraries" "mods" "resources" "scripts")
  local files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png")
  local config_folder="config"
  local backup_folder="/data/gtnh-upgrade-$current_datetime"
  local journey_map_folder="JourneyMapServer"

  # Backup the config folder
  if [[ -d "/data/$config_folder" ]]; then
      log "Creating backup of /data/$config_folder at $backup_folder"
      cp -r "/data/$config_folder" "$backup_folder"
  fi

# Update resources from unpacked server files to /data
  for resource in "${folders_to_update[@]}" "$config_folder" "${files_to_update[@]}"; do
    local resource_path="/data/$resource"
    local new_resource_path="$base_dir/$resource"

    debug "Updating resource: $resource_path with new resource: $new_resource_path"
    updateGTNHresource "$resource_path" "$new_resource_path"
  done

  # Restore JourneyMapServer folder from backup
  if [[ -d "$backup_folder/$journey_map_folder" ]]; then
    if [[ ! -d "/data/$config_folder" ]]; then
      log "/data/$config_folder folder does not exist. Creating it now."
      mkdir -p "/data/$config_folder"
    fi
      log "Restoring $journey_map_folder to /data/$config_folder"
      cp -r "$backup_folder/$journey_map_folder" "/data/$config_folder/"
  else
      logWarning "$journey_map_folder not found in backup!"
  fi

  # Copy the changelog file to /data
  local gtnh_changelog_file=""
  gtnh_changelog_file=$(mc-image-helper find --max-depth=1 --type=file --name=changelog*.md "$base_dir")
  if [[ -n "$gtnh_changelog_file" ]]; then
    debug "Found changelog file: $gtnh_changelog_file"
    log "Copying changelog file to /data"
    cp -f "$gtnh_changelog_file" /data/
  fi
}

function handleGTNH() {

  : "${GTNH_PACK_VERSION:=latest}"
  : "${GTNH_DELETE_BACKUPS:=false}"
  : "${SKIP_GTNH_UPDATE_CHECK:=false}"
  debug "GTNH VAR CHECK: GTNH_DELETE_BACKUPS=$GTNH_DELETE_BACKUPS, GTNH_PACK_VERSION=$GTNH_PACK_VERSION, TYPE=$TYPE, SKIP_GTNH_UPDATE_CHECK=$SKIP_GTNH_UPDATE_CHECK"

  if isTrue "$GTNH_DELETE_BACKUPS"; then
    deleteGTNHbackup
  fi

  if [[ -n "$GTNH_PACK_VERSION" ]] && isFalse "$SKIP_GTNH_UPDATE_CHECK" ; then
    
    getGTNHdownloadPath
    log "Server files located! Will proceed update $gtnh_download_path."


    # Decide if update or install is needed or not.
    if [[ ! -f /data/.gtnh-version || "$(basename "$gtnh_download_path")" != "$(cat /data/.gtnh-version)" ]]; then
      log "Update/Install required: /data/.gtnh-version is missing or does not match the selected version $(basename "$gtnh_download_path")."

      # Download and unpack GTNH server files
      downloadGTNH
      log "GTNH server files downloaded and unpacked to $base_dir."

      # Split installation from update path. Check for version file.
      if [[ -f /data/.gtnh-version ]]; then
        log ".gtnh-version file detected! Assuming old version already exists. Proceed updating existing server..."
        updateGTNH
      else
        log "No .gtnh-version file detected! Assuming no old server exists. Proceed installing new server..."
        cp -R -f "${base_dir}"/* /data
      fi

      # Update .gtnh-version
      basename "$gtnh_download_path" > /data/.gtnh-version

      # Cleaning up temporary files
      rm -rf /data/.tmp
    
    else
      log "No update required: /data/.gtnh-version matches the selected version $(basename "$gtnh_download_path")."
    fi
  else
    log "SKIP_GTNH_UPDATE_CHECK=$SKIP_GTNH_UPDATE_CHECK ... Skipping GTNH Update/Install"
  fi
}

# Set server.properties defaults suitable for gtnh servers
log "Applying GTNH optimized server defaults"
export ALLOW_FLIGHT="${ALLOW_FLIGHT:=true}"
export LEVEL_TYPE="${LEVEL_TYPE:=rwg}"
export DIFFICULTY="${DIFFICULTY:=3}"
export ENABLE_COMMAND_BLOCK="${ENABLE_COMMAND_BLOCK:=true}"
export MOTD="${MOTD:="Greg Tech New Horizons $GTNH_PACK_VERSION"}"
debug "Set MOTD=$MOTD, ENABLE_COMMAND_BLOCK=$ENABLE_COMMAND_BLOCK, DIFFICULTY=$DIFFICULTY, LEVEL_TYPE=$LEVEL_TYPE, ALLOW_FLIGHT=$ALLOW_FLIGHT"

isDebugging && set -x

ensureRemoveAllModsOff "MODPACK_PLATFORM=GTNH"

java_version=$(mc-image-helper java-release)
if (( java_version == 8 )); then
  export SERVER=/data/forge-1.7.10-10.13.4.1614-1.7.10-universal.jar
elif (( java_version >= 17 )); then
  export SERVER=/data/lwjgl3ify-forgePatches.jar
else 
  logError "Greg Tech New Horizons only supports the following Java versions: 8, 17 or later"
  exit 1
fi

  log "TYPE=GTNH, setting Minecraft version to 1.7.10"
  export VERSION=1.7.10

# Start setup gtnh server files
handleGTNH

export USES_MODS=true

exec "$(dirname "$0")/start-setupWorld" "$@"
