@echo off
setlocal EnableExtensions EnableDelayedExpansion

REM ============================================================
REM SuddenGaming.net - 7 Days To Die Mod Switcher
REM Vanilla / Modded / The Wasteland
REM ============================================================
set "VER=v2026-09-22.02"
set "ROOT=C:\7d2d"
set "PACKAGES=%ROOT%\packages"
set "BACKUPS=%ROOT%\backups"
set "ROLLBACK=%BACKUPS%\Mods_rollback"
set "VANILLABASE=%BACKUPS%\Mods_vanilla_baseline"
set "EXTRACT=%ROOT%\_extract"
set "LOG=%ROOT%\modswitcher.log"
set "SAVEDPATH=%ROOT%\gamepath.txt"

set "ZIP_MODDED=%PACKAGES%\7d2dmodded.zip"
set "SHA_MODDED=%PACKAGES%\7d2dmodded.sha256"
set "ZIP_WASTE=%PACKAGES%\thewasteland.zip"
set "SHA_WASTE=%PACKAGES%\thewasteland.sha256"

set "URLBASE=https://suddenimpact.theworkpc.com/mods"
set "URL_MODDED=%URLBASE%/7d2dmodded.zip"
set "URL_MODDED_SHA=%URLBASE%/7d2dmodded.sha256"
set "URL_WASTE=%URLBASE%/thewasteland.zip"
set "URL_WASTE_SHA=%URLBASE%/thewasteland.sha256"

set "DEFAULT1=C:\Program Files (x86)\Steam\steamapps\common\7 Days To Die"
set "DEFAULT2=C:\Program Files\Steam\steamapps\common\7 Days To Die"

if /I "%~1"=="--child" goto MAIN
start "7DTD Mod Switcher %VER%" cmd /k ""%~f0" --child"
exit /b

:MAIN
title SuddenGaming.net - 7DTD Mod Switcher %VER%
color 0A

call :EnsureFolder "%ROOT%" || goto FAIL
call :EnsureFolder "%PACKAGES%" || goto FAIL
call :EnsureFolder "%BACKUPS%" || goto FAIL
call :EnsureFolder "%EXTRACT%" || goto FAIL

call :FindGame || goto FAIL

:MENU
cls
echo ============================================================
echo  SuddenGaming.net - 7 Days To Die Mod Switcher
echo  %VER%
echo ============================================================
echo  Game: !GAMEDIR!
echo.
echo   1 = Load VANILLA
echo   2 = Load MODDED
echo   3 = Load THE WASTELAND
echo   4 = Save / Update VANILLA Baseline
echo   5 = Maintenance / Cleanup
echo   6 = Exit
echo.
if not exist "%VANILLABASE%\" (
  echo   *** VANILLA BASELINE HAS NOT BEEN SAVED ***
  echo   Save it before installing mods so you can return to Vanilla.
  echo.
)
echo ============================================================
set "OPT="
set /p "OPT=Choose 1-6: "
if "%OPT%"=="1" goto DO_VANILLA
if "%OPT%"=="2" goto DO_MODDED
if "%OPT%"=="3" goto DO_WASTE
if "%OPT%"=="4" goto CAPTURE_VANILLA_MAIN
if "%OPT%"=="5" goto MAINT
if "%OPT%"=="6" goto DONE
goto MENU

:DO_VANILLA
echo.
echo Switching to VANILLA...
call :PrepareRollback || goto FAIL
if exist "!MODSDIR!\" rmdir /s /q "!MODSDIR!" || goto FAIL
call :EnsureFolder "!MODSDIR!" || goto FAIL
REM 0_TFP_Harmony is part of the game install and is safe to restore if captured.
if exist "%VANILLABASE%\" call :Mirror "%VANILLABASE%" "!MODSDIR!" || goto FAIL
goto SUCCESS

:DO_MODDED
call :EnsureVanillaBaseline || goto MENU
echo.
echo Checking SuddenGaming MODDED package...
call :EnsureCurrentPackage "%ZIP_MODDED%" "%SHA_MODDED%" "%URL_MODDED%" "%URL_MODDED_SHA%" || goto FAIL
call :PrepareRollback || goto FAIL
call :InstallZip "%ZIP_MODDED%" || goto FAIL
goto SUCCESS

:DO_WASTE
call :EnsureVanillaBaseline || goto MENU
echo.
echo Checking THE WASTELAND package...
call :EnsureCurrentPackage "%ZIP_WASTE%" "%SHA_WASTE%" "%URL_WASTE%" "%URL_WASTE_SHA%" || goto FAIL
call :PrepareRollback || goto FAIL
call :InstallZip "%ZIP_WASTE%" || goto FAIL
goto SUCCESS

:MAINT
cls
echo ============================================================
echo  Maintenance / Cleanup
echo ============================================================
echo   1 = Capture current Mods as VANILLA baseline
echo   2 = Restore emergency rollback
echo   3 = Delete legacy Mods_prev_* folders
echo   4 = Delete legacy Mods_backup_* folders
echo   5 = Clear downloaded package cache
echo   6 = Back
echo ============================================================
set "MOPT="
set /p "MOPT=Choose 1-6: "
if "%MOPT%"=="1" goto CAPTURE_VANILLA
if "%MOPT%"=="2" goto RESTORE_ROLLBACK
if "%MOPT%"=="3" goto CLEAN_PREV
if "%MOPT%"=="4" goto CLEAN_BACKUPS
if "%MOPT%"=="5" goto CLEAN_PACKAGES
if "%MOPT%"=="6" goto MENU
goto MAINT

:CAPTURE_VANILLA_MAIN
call :CaptureVanillaBaseline || goto FAIL
echo.
echo Vanilla baseline saved successfully.
pause
goto MENU

:CAPTURE_VANILLA
call :CaptureVanillaBaseline || goto FAIL
echo.
echo Vanilla baseline saved successfully.
pause
goto MAINT

:RESTORE_ROLLBACK
if not exist "%ROLLBACK%\" (
  echo No emergency rollback exists.
  pause
  goto MAINT
)
echo.
echo This replaces the current Mods folder with the last rollback.
choice /c YN /n /m "Continue? (Y/N): "
if errorlevel 2 goto MAINT
if exist "!MODSDIR!\" rmdir /s /q "!MODSDIR!"
call :EnsureFolder "!MODSDIR!" || goto FAIL
call :Mirror "%ROLLBACK%" "!MODSDIR!" || goto FAIL
echo Rollback restored.
pause
goto MAINT

:CLEAN_PREV
echo.
echo This removes legacy Mods_prev_* folders from:
echo !GAMEDIR!
choice /c YN /n /m "Continue? (Y/N): "
if errorlevel 2 goto MAINT
for /d %%D in ("!GAMEDIR!\Mods_prev_*") do if exist "%%~fD\" rmdir /s /q "%%~fD"
echo Done.
pause
goto MAINT

:CLEAN_BACKUPS
echo.
echo This removes legacy Mods_backup_* folders from:
echo %BACKUPS%
choice /c YN /n /m "Continue? (Y/N): "
if errorlevel 2 goto MAINT
for /d %%D in ("%BACKUPS%\Mods_backup_*") do if exist "%%~fD\" rmdir /s /q "%%~fD"
echo Done.
pause
goto MAINT

:CLEAN_PACKAGES
echo.
echo This deletes locally cached ZIP and SHA files. They will download again when needed.
choice /c YN /n /m "Continue? (Y/N): "
if errorlevel 2 goto MAINT
del /q "%PACKAGES%\*.zip" "%PACKAGES%\*.sha256" >nul 2>&1
echo Done.
pause
goto MAINT

REM ============================================================
REM Vanilla baseline safety
REM ============================================================
:EnsureVanillaBaseline
if exist "%VANILLABASE%\" exit /b 0
cls
echo ============================================================
echo  VANILLA BASELINE REQUIRED
echo ============================================================
echo.
echo No Vanilla baseline has been saved yet.
echo.
echo Before installing mods, the switcher should save your CURRENT
echo Mods folder so you can return to Vanilla later.
echo.
echo Only continue if your game is CURRENTLY VANILLA.
echo.
choice /c YN /n /m "Save the current Mods folder as Vanilla and continue? (Y/N): "
if errorlevel 2 exit /b 1
call :CaptureVanillaBaseline PRECONFIRMED
exit /b %errorlevel%

:CaptureVanillaBaseline
if /I "%~1"=="PRECONFIRMED" goto CAPTURE_CONFIRMED
echo.
echo ============================================================
echo  SAVE / UPDATE VANILLA BASELINE
echo ============================================================
echo.
echo WARNING:
echo Only do this while your game is currently VANILLA.
echo Saving a modded Mods folder here will make that your
echo Vanilla restore point.
echo.
choice /c YN /n /m "Is the current Mods folder VANILLA? Save it now? (Y/N): "
if errorlevel 2 exit /b 1
:CAPTURE_CONFIRMED

if exist "%VANILLABASE%\" rmdir /s /q "%VANILLABASE%"
call :EnsureFolder "%VANILLABASE%" || exit /b 1
if exist "!MODSDIR!\" call :Mirror "!MODSDIR!" "%VANILLABASE%" || exit /b 1
exit /b 0

REM ============================================================
REM Find game
REM ============================================================
:FindGame
set "GAMEDIR="
if exist "%SAVEDPATH%" (
  for /f "usebackq delims=" %%A in ("%SAVEDPATH%") do set "GAMEDIR=%%A"
  if not exist "!GAMEDIR!\7DaysToDie.exe" set "GAMEDIR="
)
if not defined GAMEDIR if exist "!DEFAULT1!\7DaysToDie.exe" set "GAMEDIR=!DEFAULT1!"
if not defined GAMEDIR if exist "!DEFAULT2!\7DaysToDie.exe" set "GAMEDIR=!DEFAULT2!"
if not defined GAMEDIR (
  echo Could not automatically locate 7 Days To Die.
  set /p "GAMEDIR=Paste the game folder path: "
)
if not exist "!GAMEDIR!\7DaysToDie.exe" (
  echo ERROR: 7DaysToDie.exe not found.
  exit /b 1
)
> "%SAVEDPATH%" echo !GAMEDIR!
set "MODSDIR=!GAMEDIR!\Mods"
exit /b 0

REM ============================================================
REM Package updater
REM SHA file format: hash only OR standard "hash  filename"
REM ============================================================
:EnsureCurrentPackage
set "PZIP=%~1"
set "PSHA=%~2"
set "PURL=%~3"
set "PSHAURL=%~4"
set "TMPSHA=%PSHA%.new"
set "TMPZIP=%PZIP%.download"

echo Downloading current checksum...
call :Download "%PSHAURL%" "%TMPSHA%" || (
  echo ERROR: Could not download checksum.
  exit /b 1
)

call :ReadExpectedHash "%TMPSHA%" REMOTEHASH
if not defined REMOTEHASH (
  echo ERROR: Downloaded checksum file is invalid.
  del /q "%TMPSHA%" >nul 2>&1
  exit /b 1
)

set "LOCALHASH="
if exist "%PZIP%" call :GetHash "%PZIP%" LOCALHASH

if /I "!LOCALHASH!"=="!REMOTEHASH!" (
  move /y "%TMPSHA%" "%PSHA%" >nul
  echo Package is already current. No ZIP download needed.
  exit /b 0
)

echo New or changed package detected.
echo Downloading %~nx1...
del /q "%TMPZIP%" >nul 2>&1
call :Download "%PURL%" "%TMPZIP%" || (
  echo ERROR: ZIP download failed.
  del /q "%TMPSHA%" "%TMPZIP%" >nul 2>&1
  exit /b 1
)

call :GetHash "%TMPZIP%" DOWNHASH
if /I not "!DOWNHASH!"=="!REMOTEHASH!" (
  echo ERROR: Downloaded ZIP failed SHA-256 verification.
  echo Expected: !REMOTEHASH!
  echo Received: !DOWNHASH!
  del /q "%TMPSHA%" "%TMPZIP%" >nul 2>&1
  exit /b 1
)

move /y "%TMPZIP%" "%PZIP%" >nul || exit /b 1
move /y "%TMPSHA%" "%PSHA%" >nul || exit /b 1
echo SHA-256 verified successfully.
exit /b 0

:Download
set "DURL=%~1"
set "DOUT=%~2"
del /q "%DOUT%" >nul 2>&1
where curl.exe >nul 2>&1
if not errorlevel 1 (
  curl.exe -fL --retry 2 --connect-timeout 15 -o "%DOUT%" "%DURL%"
  if not errorlevel 1 if exist "%DOUT%" exit /b 0
)
echo curl failed or unavailable. Trying PowerShell...
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
  "$ProgressPreference='Continue'; try { Invoke-WebRequest -Uri '%DURL%' -OutFile '%DOUT%' -UseBasicParsing -ErrorAction Stop; exit 0 } catch { Write-Host $_.Exception.Message; exit 1 }"
if not errorlevel 1 if exist "%DOUT%" exit /b 0
exit /b 1

:GetHash
set "%~2="
for /f "usebackq delims=" %%H in (`powershell -NoProfile -Command "(Get-FileHash -LiteralPath '%~1' -Algorithm SHA256).Hash.ToUpperInvariant()"`) do set "%~2=%%H"
exit /b 0

:ReadExpectedHash
set "%~2="
for /f "usebackq tokens=1" %%H in ("%~1") do (
  set "%~2=%%H"
  goto READHASH_DONE
)
:READHASH_DONE
exit /b 0

REM ============================================================
REM Install / rollback
REM ============================================================
:PrepareRollback
if exist "%ROLLBACK%\" rmdir /s /q "%ROLLBACK%"
call :EnsureFolder "%ROLLBACK%" || exit /b 1
if exist "!MODSDIR!\" call :Mirror "!MODSDIR!" "%ROLLBACK%" || exit /b 1
exit /b 0

:InstallZip
set "ZIPFILE=%~1"
set "WORK=%EXTRACT%\work"
if exist "%WORK%\" rmdir /s /q "%WORK%"
call :EnsureFolder "%WORK%" || exit /b 1

echo Extracting package...
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
  "try { Expand-Archive -LiteralPath '%ZIPFILE%' -DestinationPath '%WORK%' -Force -ErrorAction Stop; exit 0 } catch { Write-Host $_.Exception.Message; exit 1 }"
if errorlevel 1 exit /b 1

if exist "!MODSDIR!\" rmdir /s /q "!MODSDIR!"
call :EnsureFolder "!MODSDIR!" || exit /b 1

if exist "%WORK%\Mods\" (
  call :Mirror "%WORK%\Mods" "!MODSDIR!" || exit /b 1
) else (
  call :Mirror "%WORK%" "!MODSDIR!" || exit /b 1
)
rmdir /s /q "%WORK%" >nul 2>&1
exit /b 0

:Mirror
call :EnsureFolder "%~2" >nul 2>&1
robocopy "%~1" "%~2" /MIR /R:2 /W:1 /NFL /NDL /NP /NJH /NJS >> "%LOG%" 2>&1
if errorlevel 8 exit /b 1
exit /b 0

:EnsureFolder
if exist "%~1\" exit /b 0
if exist "%~1" del /f /q "%~1" >nul 2>&1
mkdir "%~1" >nul 2>&1
if exist "%~1\" exit /b 0
exit /b 1

:SUCCESS
echo.
echo ============================================================
echo  COMPLETED SUCCESSFULLY
echo ============================================================
echo.
echo You can now start 7 Days To Die.
echo.
echo Press any key to close...
pause >nul
exit

:FAIL
echo.
echo ============================================================
echo  Fuck. No bueno. Something failed.
echo ============================================================
echo Check: %LOG%
echo.
pause
goto MENU

:DONE
exit
