#!/bin/env bash

MC_VERSION=${MC_VERSION}

MC_LOADER=${MC_LOADER=}
MC_LOADER_VERSION=${MC_LOADER_VERSION}

JAVA_VERSION=${JAVA_VERSION:-"temurin@21"}
JAVA_HOME=/data/java/${JAVA_VERSION}
JAR=${JAR:-"server.jar"}

XMS=${XMS:-2G}
XMX=${XMX:-4G}

MEM=${MEMORY:-2G}
ADD_ARGS=${ADD_ARGS:-""}

PUID="${PUID:-1000}"
PGID="${PGID:-1000}"

PATH=${JAVA_HOME}/bin:$PATH

# Set Permissions for data folder
setperms() {
  echo -e "|_______________________________________________________|"
  echo -e "|##--------------- Setting Permissions ---------------##|"
  echo -e "|#| Setting permissions to UID:${PUID} and GID:${PGID}"
  sudo usermod -u ${PUID} minecraft >/dev/null 2>&1
  sudo groupmod -g ${PGID} minecraft >/dev/null 2>&1
  sudo chown -R ${PUID}:${PGID} /data >/dev/null 2>&1
  echo -e "|#|---------------------------------------------------|#|"
  sleep 2
  echo -e "|#|                     DONE"
  echo -e "|##---------------------------------------------------##|"
  sleep 2
}

# Crash function
crash() {
  sleep 5
  echo "Exit Complete"
  exit 1
}

# Set Eula
setEula() {
  cat <<EOF > eula.txt
#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).
eula=true
EOF
}

# Check for Java, and install if neccesary
javaCheck() {
  JAVA_HOME=/data/java/${JAVA_VERSION}
  if [[ -f "$HOME/.jabba/jabba.sh" ]]; then
    source $HOME/.jabba/jabba.sh
  else
    echo "Something went wrong with locating jabba(the java installer)"
    exit 0
  fi

  if [[ ! -n "${JAVA_VERSION}" ]]; then
    echo "NO JAVA_VERSION ENVIRONMENT VARIABLE SET SET IT"
    crash
  fi

  if [[ ! -f "/data/java/${JAVA_VERSION}/bin/java" ]]; then
    rm -rf /data/java/${JAVA_VERSION}
    jabba install ${JAVA_VERSION} -o /data/java/${JAVA_VERSION}
  fi
  PATH=${JAVA_HOME}/bin:$PATH
  JAVA="java"
}

newForge() {
  if [[ "$(printf '%s\n' "1.17.1" "$MC_VERSION" | sort -V | head -n1)" = "1.17.1" ]]; then
    NEW_FORGE=true
  else
    NEW_FORGE=false
  fi
}

# Vanilla
getVanilla() {
  echo "Not yet implemented"
}

# Paper Server
getPaper() {
  SERVER_TYPE="Paper Minecraft"
  if [[ ! -f server.jar ]]; then
    LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${MC_LOADER}/versions/${MC_VERSION}/builds |
      jq -r '.builds | map(select(.channel == "default") | .build) | .[-1]')

    if [ "$LATEST_BUILD" != "null" ]; then
      JAR_NAME=${MC_LOADER}-${MC_VERSION}-${LATEST_BUILD}.jar
      PAPERMC_URL="https://api.papermc.io/v2/projects/${MC_LOADER}/versions/${MC_VERSION}/builds/${LATEST_BUILD}/downloads/${JAR_NAME}"

      # Download the latest Paper version
      curl -o server.jar $PAPERMC_URL
      echo "Download completed"
      echo "Minecraft Version: ${MC_VERSION}"
      echo "Paper Version: ${LATEST_BUILD}"
    else
      echo "No stable build for version $MC_VERSION found :("
    fi
  fi
}

# Fabric Server
getFabric() {
  SERVER_TYPE="Fabric Minecraft"
  LATEST_BUILD=$(curl -s https://meta.fabricmc.net/v2/versions/loader/${MC_VERSION} | jq -s '.[] .[0] .loader .version' | tr -d '"')
  LATEST_INSTALLER=$(curl -s https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml | xmllint --xpath "/metadata/versioning/latest/text()" -)
  
  if [ "$MC_VERSION" != "null" ]; then
    VER=$MC_VERSION
  else
    echo "Minecraft version not set"
    exit 1
  fi

  if [ "$MC_LOADER_VERSION" == "null" ]; then
    DL_URL=https://meta.fabricmc.net/v2/versions/loader/${MC_VERSION}/${LATEST_BUILD}/${LATEST_INSTALLER}/server/jar
  else
    DL_URL=https://meta.fabricmc.net/v2/versions/loader/${MC_VERSION}/${MC_LOADER_VERSION}/${LATEST_INSTALLER}/server/jar
  fi

  if [ "$LATEST_BUILD" != "null" ]; then
    echo "$DL_URL"
    curl -o server.jar ${DL_URL}
  else
    echo "TODO ERROR TEXT"
  fi

}

# Forge Server
getForge() {
  SERVER_TYPE="Forge Server"

  if [[ -n "$MC_VERSION" ]]; then
    VER_MINECRAFT=$MC_VERSION
    if [[ -n "$MC_LOADER_VERSION" ]]; then
      VER_LOADER=$MC_LOADER_VERSION
      DL_URL=https://maven.minecraftforge.net/net/minecraftforge/forge/${VER_MINECRAFT}-${VER_LOADER}/forge-${VER_MINECRAFT}-${VER_LOADER}-installer.jar
    else
      LATEST_BUILD=$(curl -s https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json | jq -r ".promos[\"${VER_MINECRAFT}-latest\"]")
      VER_LOADER=$LATEST_BUILD
      DL_URL=https://maven.minecraftforge.net/net/minecraftforge/forge/${VER_MINECRAFT}-${VER_LOADER}/forge-${VER_MINECRAFT}-${VER_LOADER}-installer.jar
    fi
  else
    echo "Minecraft version not set"
    exit 1
  fi

  if [[ -n "$DL_URL" ]]; then
    echo "$DL_URL"
    rm -rf server.jar
    curl -o forge-install.jar ${DL_URL}
    echo "$JAVA -jar forge-install.jar --installServer"
    $JAVA -jar forge-install.jar --installServer

    # if greater or equalt to 1.17.1
    if [[ "$(printf '%s\n' "1.17.1" "$MC_VERSION" | sort -V | head -n1)" = "1.17.1" ]]; then
      NEW_FORGE=true
      rm -f forge-install.jar
      rm -f forge-install.jar.log

    # less than 1.71.1
    else
      NEW_FORGE=false
      rm -f forge-install.jar
      rm -f forge-install.jar.log
      ln -s forge-"${VER_MINECRAFT}"-"${VER_LOADER}".jar server.jar
    fi

    touch server.properties

  else
    echo "No Valid Download URL"
  fi
}

# Neoforge
getNeoForge() {
  SERVER_TYPE="NeoForge Server"

  if [[ -n "$MC_VERSION" ]]; then
    VER_MINECRAFT=$MC_VERSION
    if [[ -n "$MC_LOADER_VERSION" ]]; then
      VER_LOADER=$MC_LOADER_VERSION
      DL_URL=https://maven.neoforged.net/releases/net/neoforged/neoforge/$VER_LOADER/neoforge-$VER_LOADER-installer.jar
    else
      echo "Minecraft version not set"
      exit 1
    fi
  fi

  if [[ -n "$DL_URL" ]]; then
    echo "$DL_URL"
    rm -rf server.jar

    curl -o neoforge-$VER_LOADER-installer.jar ${DL_URL}
    $JAVA -jar neoforge-$VER_LOADER-installer.jar --installServer --server.jar

    mv server.jar neoforge-$VER_LOADER.jar
    ln -s neoforge-$VER_LOADER.jar server.jar

    touch server.properties

    rm -f neoforge-$VER_LOADER-installer.jar
    rm -f neoforge-$VER_LOADER-installer.jar.log
    rm -f README.txt
    rm -f run.bat

  else
    echo "No Valid Download URL"
  fi
  
}

# Server route choice
serverSelect() {
  mkdir -p /data/server
  cd /data/server || exit
  if [[ -f "server.jar" ]] || [[ -f "run.sh" ]]; then
    echo "Found what appears to be a server, sending it"
  else
    case $MC_LOADER in
    vanilla)
      getVanilla
      ;;
    paper)
      getPaper
      ;;
    fabric)
      getFabric
      ;;
    forge)
      getForge
      ;;
    neoforge)
      getNeoForge
      ;;
    *)
      echo "Server of type ${MC_LOADER} is not recognized."
      crash
      ;;
    esac
  fi
}

# Build out java command
buildCommand() {
  JAVA_ARGS="-Xms${XMS} -Xmx${XMX}"
  if [[ -n $ADD_ARGS ]]; then
    RUN_STRING="${ADD_ARGS} ${JAVA_ARGS} -jar ${JAR} nogui"
  else
    RUN_STRING="${JAVA_ARGS} -jar ${JAR} nogui"
  fi
}

setperms
javaCheck
serverSelect
buildCommand

setEula

serverInfoWrite() {
  cat <<EOF > server.info
MC_VERSION=$MC_VERSION

MC_LOADER=$MC_LOADER
MC_LOADER_VERSION=$MC_LOADER_VERSION

JAVA_VERSION=$JAVA_VERSION
JAR=$JAR

XMS=$XMS
XMX=$XMX
ADD_ARGS=${ADD_ARGS:-"NONE"}

PUID=$PUID
PGID=$PGID
EOF
}

## ----------------- SEND IT ----------------- ##
while true; do
  cd /data/server || exit
  if [[ ! -f "server.properties" ]]; then touch "server.properties"; fi

  if [[ -f $JAR || -f "run.sh" ]]; then
    echo -e "|_______________________________________________________|"
    echo -e "|##----------------- Server Starting -----------------##|"
    echo -e "|#| Minecraft Version: $MC_VERSION"
    echo -e "|#| "
    echo -e "|#| Loader Type: ${SERVER_TYPE:-$MC_LOADER}"
    echo -e "|#| Loader Version: $MC_LOADER_VERSION"
    echo -e "|#| "
    echo -e "|#| Java Version: $JAVA_VERSION"
    echo -e "|#| Jar: $JAR"
    echo -e "|#| Memory Allocated: "
    echo -e "|#|    Xms: $XMS"
    echo -e "|#|    Xmx: $XMX"
    echo -e "|#| Additional Args: ${ADD_ARGS:-"NONE"}"
    echo -e "|#| "
    echo -e "|#| Running as:"
    echo -e "|#|    User:  $PUID"
    echo -e "|#|    Group: $PGID"
    echo -e "|#| "
    if [[ ! $NEW_FORGE ]]; then
      echo -e "|#| Run Command:"
      echo -e "|#|    java $RUN_STRING"
    fi
    echo -e "|##---------------------------------------------------##|"
    echo -e "|-------------------------------------------------------|"
    echo -e " "
    serverInfoWrite
    newForge
    if [[ "$MC_LOADER" == "neoforge" ]]; then
      exec java @user_jvm_args.txt @libraries/net/neoforged/neoforge/"$MC_LOADER_VERSION"/unix_args.txt "$@"
    elif [[ "$MC_LOADER" == "forge" ]] && [[ $NEW_FORGE == "true" ]]; then
      exec java @user_jvm_args.txt @libraries/net/minecraftforge/forge/"$MC_VERSION"-"$MC_LOADER_VERSION"/unix_args.txt "$@"
    else
      echo "java $RUN_STRING"
      exec java $RUN_STRING
    fi
  else
    echo "Server Not Found."
    crash
  fi
done
