function Show-Header {
    Clear-Host
    Write-Host "====================================" -ForegroundColor Cyan
    Write-Host "      UNIFIED SHEEPIT LAUNCHER" -ForegroundColor Cyan
    Write-Host "====================================" -ForegroundColor Cyan
    Write-Host
}

$SheepItJarUrls = @(
    'https://www.sheepit-renderfarm.com/media/applet/client-latest.php',
    'https://www.sheepit-renderfarm.com/media/applet/client-latest.jar'
)
$script:SheepItUsername = $null
$script:SheepItRenderKey = $null

function Initialize-SheepItCredentials {
    if (-not $script:SheepItUsername) {
        $script:SheepItUsername = "RaincloudTheDragon"
    }

    if (-not $script:SheepItRenderKey) {
        $script:SheepItRenderKey = "IfCOWBHFQpceG0601DmyrwOOJOAp2UJAQ0O0X0jF"
    }
}

$workers = @(
    @{ ID = 1; Name = "i9kf"; SSHArgs = "-t i9kf"; Enabled = $true },
    @{ ID = 2; Name = "blender-boss"; SSHArgs = "-t blender-boss"; Enabled = $true },
    @{ ID = 3; Name = "max"; SSHArgs = "-t max"; Enabled = $true },
    @{ ID = 4; Name = "masterbox"; SSHArgs = "-t masterbox"; Enabled = $true },
    @{ ID = 5; Name = "echo"; SSHArgs = "-t echo"; Enabled = $true },
    @{ ID = 6; Name = "i9-13ks"; SSHArgs = "-t -p 22146 i9-13ks"; Enabled = $true }
)

function Get-RemoteSheepItCommand {
    param(
        [string]$RenderKey,
        [string]$Username
    )

    $safeKey = $RenderKey -replace "'", "''"
    $safeUser = $Username -replace "'", "''"

    $urlLiteral = '@(' + (($SheepItJarUrls | ForEach-Object { "'$_'" }) -join ', ') + ')'

@"
`$ErrorActionPreference = 'Stop'

try {
    `$appData = [Environment]::GetFolderPath('ApplicationData')
    `$sheepDir = Join-Path `$appData 'sheepit'
    if (-not (Test-Path `$sheepDir)) {
        New-Item -Path `$sheepDir -ItemType Directory -Force | Out-Null
    }

    `$jarPath = Join-Path `$sheepDir 'sheepit-client.jar'
    `$urls = $urlLiteral
    `$headers = @{ 'User-Agent' = 'Mozilla/5.0' }

    if (Test-Path `$jarPath) {
        Write-Host "SheepIt client already present at `$jarPath. Skipping download." -ForegroundColor Green
    }
    else {
        `$downloaded = `$false

        foreach (`$url in `$urls) {
            Write-Host "Downloading SheepIt client from `$url..." -ForegroundColor Cyan
            try {
                Invoke-WebRequest -Uri `$url -OutFile `$jarPath -UseBasicParsing -Headers `$headers
                `$downloaded = `$true
                Write-Host "Download complete." -ForegroundColor Green
                break
            }
            catch {
                Write-Host ("Download failed from {0}: {1}" -f `$url, `$_.Exception.Message) -ForegroundColor Yellow
            }
        }

        if (-not `$downloaded) {
            throw 'Unable to download SheepIt client from any known URL.'
        }
    }

    Write-Host "Starting SheepIt client..." -ForegroundColor Cyan
    
    # Check and fix problematic environment variables that can cause boot class path errors
    `$envVarsFixed = `$false
    
    # Check JAVA_HOME - invalid values like '\' or empty can cause issues
    if (`$env:JAVA_HOME) {
        if (`$env:JAVA_HOME -eq '\' -or `$env:JAVA_HOME.Trim() -eq '' -or -not (Test-Path `$env:JAVA_HOME)) {
            Write-Host "Warning: Invalid JAVA_HOME detected ('`$env:JAVA_HOME'). Temporarily unsetting..." -ForegroundColor Yellow
            Remove-Item Env:\JAVA_HOME -ErrorAction SilentlyContinue
            `$envVarsFixed = `$true
        }
    }
    
    # Check JAVA_TOOL_OPTIONS - invalid values can cause boot class path errors
    if (`$env:JAVA_TOOL_OPTIONS) {
        if (`$env:JAVA_TOOL_OPTIONS -eq '\' -or `$env:JAVA_TOOL_OPTIONS.Trim() -eq '') {
            Write-Host "Warning: Invalid JAVA_TOOL_OPTIONS detected ('`$env:JAVA_TOOL_OPTIONS'). Temporarily unsetting..." -ForegroundColor Yellow
            Remove-Item Env:\JAVA_TOOL_OPTIONS -ErrorAction SilentlyContinue
            `$envVarsFixed = `$true
        }
    }
    
    if (`$envVarsFixed) {
        Write-Host "Environment variables fixed. Proceeding with Java launch..." -ForegroundColor Green
    }
    
    # Check Java version
    try {
        `$javaOutput = java -version 2>&1
        `$javaVersion = `$javaOutput | Select-Object -First 1
        Write-Host "Java version: `$javaVersion" -ForegroundColor Gray
    }
    catch {
        Write-Host "Warning: Could not determine Java version" -ForegroundColor Yellow
    }
    
    Set-Location `$sheepDir
    
    # Use -XX:+IgnoreUnrecognizedVMOptions to handle any incompatible JVM args
    # This flag helps with Java 9+ compatibility issues
    `$javaArgs = @('-XX:+IgnoreUnrecognizedVMOptions', '-jar', `$jarPath, 
                   '-ui', 'text', '--log-stdout', '--verbose', 
                   '-gpu', 'OPTIX_0', '-login', '${safeUser}', '-password', '${safeKey}')
    
    try {
        & java @javaArgs
    }
    catch {
        Write-Host ('Java execution error: {0}' -f `$_.Exception.Message) -ForegroundColor Red
        Write-Host "If the error persists, try reinstalling Java (Temurin 21 recommended)." -ForegroundColor Yellow
        throw
    }
}
catch {
    Write-Host ('Error: {0}' -f `$_.Exception.Message) -ForegroundColor Red
    Write-Host ('Stack trace: {0}' -f `$_.ScriptStackTrace) -ForegroundColor DarkRed
}
"@
}

function New-SheepItSessionScript {
    param(
        [object]$Worker,
        [string]$RemoteCommand
    )
    
    $rawArgs = @($Worker.SSHArgs -split '\s+' | Where-Object { $_ -and $_.Trim().Length -gt 0 })
    $sshArgsJson = if ($rawArgs) { ($rawArgs | ConvertTo-Json -Compress) } else { '[]' }
    $targetHost = ($rawArgs | Where-Object { $_ -notmatch '^-{1,2}' } | Select-Object -Last 1)
    $hostLiteral = if ($targetHost) { "'" + ($targetHost -replace "'", "''") + "'" } else { '$null' }
    $portValue = $null
    for ($i = 0; $i -lt $rawArgs.Count; $i++) {
        if ($rawArgs[$i] -eq '-p' -and $i -lt ($rawArgs.Count - 1)) {
            $portValue = $rawArgs[$i + 1]
            break
        }
    }
    $portLiteral = if ($portValue) { "'" + ($portValue -replace "'", "''") + "'" } else { '$null' }
    $remoteScriptBase64 = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($RemoteCommand))
    
    $scriptContent = @"
Write-Host 'Connecting to $($Worker.Name)...' -ForegroundColor Cyan
`$sshArgs = ConvertFrom-Json '$sshArgsJson'
`$targetHost = $hostLiteral
`$port = $portLiteral
`$scriptBase64 = '$remoteScriptBase64'

if (-not `$targetHost) {
    Write-Host "Unable to determine SSH host for $($Worker.Name)." -ForegroundColor Red
    return
}

`$localTemp = [System.IO.Path]::GetTempFileName() + '.ps1'
`$remoteScript = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String(`$scriptBase64))
Set-Content -Path `$localTemp -Value `$remoteScript -Encoding UTF8

`$remoteFile = "sheepit-$([System.Guid]::NewGuid().ToString()).ps1"

`$scpArgs = @('-o','ServerAliveInterval=60','-o','ServerAliveCountMax=30')
if (`$port) {
    `$scpArgs += '-P'
    `$scpArgs += `$port
}
`$scpArgs += `$localTemp
`$scpArgs += ("${targetHost}:`$remoteFile")

Write-Host "Transferring SheepIt script to `$targetHost..." -ForegroundColor Gray
& scp @scpArgs
if (`$LASTEXITCODE -ne 0) {
    Write-Host "Failed to copy script to `$targetHost." -ForegroundColor Red
    Remove-Item `$localTemp -ErrorAction SilentlyContinue
    return
}

`$sshBase = @('-o','ServerAliveInterval=60','-o','ServerAliveCountMax=30') + `$sshArgs
`$execArgs = `$sshBase + @('powershell','-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',"`$remoteFile")

Write-Host "Starting SheepIt client on `$targetHost..." -ForegroundColor Cyan
& ssh @execArgs

Write-Host "Cleaning up remote script..." -ForegroundColor Gray
`$cleanupArgs = `$sshBase + @('powershell','-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-Command',"`$ErrorActionPreference='SilentlyContinue'; Remove-Item -LiteralPath ``"$remoteFile``" -ErrorAction SilentlyContinue")
& ssh @cleanupArgs | Out-Null

Remove-Item `$localTemp -ErrorAction SilentlyContinue
Write-Host "`nSSH session ended." -ForegroundColor Yellow
Read-Host "Press Enter to close"
"@
    
    return $scriptContent
}

function Start-SheepItTab {
    param(
        [string]$Title,
        [string]$Content
    )

    $tempScript = [System.IO.Path]::GetTempFileName() + '.ps1'
    Set-Content -Path $tempScript -Value $Content -Encoding UTF8

    if (Get-Command wt.exe -ErrorAction SilentlyContinue) {
        Start-Process wt.exe -ArgumentList "-w 0 new-tab --title `"$Title`" powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -File `"$tempScript`""
    } else {
        Start-Process powershell -ArgumentList "-NoLogo -NoProfile -ExecutionPolicy Bypass -File `"$tempScript`""
    }
}

function Start-SheepItWorker {
    param([object]$Worker)

    if (-not $Worker.Enabled) {
        Write-Host "$($Worker.Name) is not enabled for SheepIt." -ForegroundColor Yellow
        return
    }

    Initialize-SheepItCredentials

    $remoteCommand = Get-RemoteSheepItCommand -RenderKey $script:SheepItRenderKey -Username $script:SheepItUsername
    $sessionScript = New-SheepItSessionScript -Worker $Worker -RemoteCommand $remoteCommand
    $title = "$($Worker.Name) - SheepIt"

    Start-SheepItTab -Title $title -Content $sessionScript
    Write-Host "Opened SheepIt session for $($Worker.Name) in a new terminal tab." -ForegroundColor Green
}

function Start-AllSheepIt {
    Initialize-SheepItCredentials

    $targets = $workers | Where-Object { $_.Enabled }

    if (-not $targets) {
        Write-Host "No systems are ready for SheepIt." -ForegroundColor Yellow
        return
    }

    foreach ($worker in $targets) {
        Start-SheepItWorker -Worker $worker
        Start-Sleep -Milliseconds 200
    }
}

function Select-SheepItWorker {
    while ($true) {
        Show-Header
        Write-Host "Select a system:" -ForegroundColor Magenta

        foreach ($worker in $workers) {
            $status = if ($worker.Enabled) { "ready" } else { "disabled" }
            $color = if ($worker.Enabled) { "Green" } else { "DarkYellow" }
            Write-Host ("{0}. {1} ({2})" -f $worker.ID, $worker.Name, $status) -ForegroundColor $color
        }

        Write-Host "B. Back" -ForegroundColor Yellow
        $selection = Read-Host "Choose system"

        if ($selection -match '^[Bb]$') {
            return
        }

        if ($selection -match '^\d+$') {
            $id = [int]$selection
            $worker = $workers | Where-Object { $_.ID -eq $id }

            if ($worker) {
                Start-SheepItWorker -Worker $worker
                Write-Host
                Read-Host "Press Enter to return to the main menu" | Out-Null
                return
            }

            Write-Host "Unknown selection." -ForegroundColor Red
            Start-Sleep -Seconds 1
        }
        else {
            Write-Host "Invalid input." -ForegroundColor Red
            Start-Sleep -Seconds 1
        }
    }
}

Initialize-SheepItCredentials

while ($true) {
    Show-Header
    Write-Host "Main Menu:" -ForegroundColor Magenta
    Write-Host "1. Launch SheepIt on a single system" -ForegroundColor Yellow
    Write-Host "2. Launch SheepIt on all ready systems" -ForegroundColor Yellow
    Write-Host "3. Exit" -ForegroundColor Yellow

    $choice = Read-Host "Select option (1-3)"

    switch ($choice) {
        '1' { Select-SheepItWorker }
        '2' {
            Start-AllSheepIt
            Write-Host
            Read-Host "Press Enter to return to the main menu" | Out-Null
        }
        '3' { break }
        default {
            Write-Host "Invalid selection." -ForegroundColor Red
            Start-Sleep -Seconds 1
        }
    }
}

Write-Host "`nExiting SheepIt launcher." -ForegroundColor Cyan

