param(
    [string]$GameRoot = "D:\SteamLibrary\steamapps\common\ProjectZomboid"
)

$ErrorActionPreference = "Stop"

$repoRoot = Split-Path -Parent $PSScriptRoot
$toolsDir = Join-Path $repoRoot ".tools"
$classPatchDir = Join-Path $toolsDir "classpatch"
$buildDir = Join-Path $toolsDir "patcher-build"

New-Item -ItemType Directory -Force -Path $toolsDir | Out-Null
New-Item -ItemType Directory -Force -Path $classPatchDir | Out-Null
New-Item -ItemType Directory -Force -Path $buildDir | Out-Null

$javaExe = Join-Path $GameRoot "jre64\bin\java.exe"
if (-not (Test-Path $javaExe)) { throw "java.exe not found at $javaExe" }

$clientJar = Join-Path $GameRoot "projectzomboid.jar"
$dedicatedJar = Join-Path $GameRoot "java\projectzomboid.jar"
$gameJar = $null
$targetClasses = @()

if (Test-Path $clientJar) {
    $gameJar = $clientJar
    $targetClasses += (Join-Path $GameRoot "zombie\vehicles\BaseVehicle.class")
}
if (Test-Path $dedicatedJar) {
    $gameJar = $dedicatedJar
    $targetClasses += (Join-Path $GameRoot "java\zombie\vehicles\BaseVehicle.class")
}
if ($null -eq $gameJar) {
    throw "projectzomboid.jar not found at either $clientJar or $dedicatedJar"
}
if ($targetClasses.Count -eq 0) {
    throw "No valid BaseVehicle.class deployment targets found under $GameRoot"
}

$ecjJar = Join-Path $toolsDir "ecj.jar"
$asmJar = Join-Path $toolsDir "asm.jar"
$asmTreeJar = Join-Path $toolsDir "asm-tree.jar"

if (-not (Test-Path $ecjJar)) {
    Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/eclipse/jdt/ecj/3.38.0/ecj-3.38.0.jar" -OutFile $ecjJar
}
if (-not (Test-Path $asmJar)) {
    Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/ow2/asm/asm/9.9/asm-9.9.jar" -OutFile $asmJar
}
if (-not (Test-Path $asmTreeJar)) {
    Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/9.9/asm-tree-9.9.jar" -OutFile $asmTreeJar
}

$patcherSource = Join-Path $PSScriptRoot "java\BaseVehicleConstraintPatch.java"
if (-not (Test-Path $patcherSource)) { throw "Missing patcher source: $patcherSource" }
$helperSource = Join-Path $PSScriptRoot "java\LandtrainConstraintAuthHelper.java"
if (-not (Test-Path $helperSource)) { throw "Missing helper source: $helperSource" }

& $javaExe -jar $ecjJar -17 -cp "$asmJar;$asmTreeJar;$gameJar" -d $buildDir $patcherSource $helperSource
if ($LASTEXITCODE -ne 0) { throw "Failed to compile BaseVehicleConstraintPatch.java/LandtrainConstraintAuthHelper.java" }

$inputClass = Join-Path $classPatchDir "BaseVehicle.original.class"
$patchedClass = Join-Path $classPatchDir "BaseVehicle.patched.class"
$helperClass = Join-Path $buildDir "zombie\vehicles\LandtrainConstraintAuthHelper.class"

Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::OpenRead($gameJar)
try {
    $entry = $zip.GetEntry("zombie/vehicles/BaseVehicle.class")
    if ($null -eq $entry) { throw "zombie/vehicles/BaseVehicle.class not found in $gameJar" }

    $entryStream = $entry.Open()
    $fileStream = [System.IO.File]::Create($inputClass)
    try {
        $entryStream.CopyTo($fileStream)
    } finally {
        $fileStream.Close()
        $entryStream.Close()
    }
} finally {
    $zip.Dispose()
}

& $javaExe -cp "$buildDir;$asmJar;$asmTreeJar" BaseVehicleConstraintPatch $inputClass $patchedClass
if ($LASTEXITCODE -ne 0) { throw "BaseVehicle class patch failed" }
if (-not (Test-Path $helperClass)) { throw "Missing compiled helper class: $helperClass" }

foreach ($targetClass in $targetClasses | Select-Object -Unique) {
    $targetDir = Split-Path -Parent $targetClass
    $backupClass = "$targetClass.landtrain.original"
    $targetHelperClass = Join-Path $targetDir "LandtrainConstraintAuthHelper.class"

    New-Item -ItemType Directory -Force -Path $targetDir | Out-Null
    if (-not (Test-Path $backupClass)) {
        if (Test-Path $targetClass) {
            Copy-Item $targetClass $backupClass -Force
        } else {
            Copy-Item $inputClass $backupClass -Force
        }
    }
    Copy-Item $patchedClass $targetClass -Force
    Copy-Item $helperClass $targetHelperClass -Force
    Write-Output "Patched BaseVehicle.class deployed to $targetClass"
    Write-Output "Deployed LandtrainConstraintAuthHelper.class to $targetHelperClass"
    Write-Output "Backup stored at $backupClass"
}

$distDir = Join-Path $repoRoot "zombie\vehicles"
$distClass = Join-Path $distDir "BaseVehicle.class"
$distHelperClass = Join-Path $distDir "LandtrainConstraintAuthHelper.class"
New-Item -ItemType Directory -Force -Path $distDir | Out-Null
Copy-Item $patchedClass $distClass -Force
Copy-Item $helperClass $distHelperClass -Force
Write-Output "Distribution class updated at $distClass"
Write-Output "Distribution helper class updated at $distHelperClass"
