# MAIN SCRIPT
# Usage example:
<#
.\BuildFullVM.ps1 -VMName "WS2025_AOFG_Template_Build" -sourceIsoPath "C:\AOFG\BuildSystemTemplate\26100.1742.240906-0331.ge_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso" -autounattendIsoPath "C:\AOFG\BuildSystemTemplate\unattend_26100.1742.240906-0331.ge_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso" -autounattendXmlIsoPath "C:\AOFG\BuildSystemTemplate\autounattend.iso" -vhdxPath "C:\AOFG\BuildSystemTemplate\WS2025_AOFG_Template_Build.vhdx" -vhdxSizeGB 40 -ramGB 8 -cpuCount 8 -productKey "MFY9F-XBN2F-TYFMP-CCV49-RMYVH" -adminPassword "Cloud123" -autounattendXmlFile "C:\Users\Administrator\source\repos\apponfly-gaming\AppOnFlyGaming.Agent.API\Scripts\BuildVM\BuildBaseVMTemplate\autounattend.xml" -isoOutputDir "C:\AOFG\BuildSystemTemplate\autounattend"

    where
        -autounattendIsoPath specifies where the autounattendIso will be CREATED
        -autounattendXmlIsoPath specifies where the autounattendXmlIso will be CREATED
        -vhdxPath specifies where the vhdx will be CREATED
This script creates a WS2025 VM from a WS2025 Installation ISO using a autounattend.xml file and installs everything needed for AOFG
#>
param(
    [Parameter(Mandatory = $false)]
    [string]$VMName = "WS2025_AOFG_Template_Build",
    [Parameter(Mandatory = $true)]
    [string]$sourceIsoPath,
    [Parameter(Mandatory = $true)]
    [string]$autounattendIsoPath,
    [Parameter(Mandatory = $true)]
    [string]$autounattendXmlIsoPath,
    [Parameter(Mandatory = $true)]
    [string]$vhdxPath,
    [Parameter(Mandatory = $false)]
    [int]$vhdxSizeGB = 40,
    [Parameter(Mandatory = $false)]
    [int]$ramGB = 8,
    [Parameter(Mandatory = $false)]
    [int]$cpuCount = 8,
    [Parameter(Mandatory = $true)]
    [string]$productKey,
    [Parameter(Mandatory = $true)]
    [string]$adminPassword,
    [Parameter(Mandatory = $true)]
    [string]$autounattendXmlFile,
    [Parameter(Mandatory = $true)]
    [string]$isoOutputDir,
    [Parameter(Mandatory = $false)]
    [string]$computerName = "AppOnFly-VPS",
    [Parameter(Mandatory = $false)]
    [bool]$openVmConnectionWindow = $false
)

Set-Location $PSScriptRoot
.("..\AOFLibrary\AOFLibrary.ps1")
$ScriptName = "BuildFullVM.ps1"
$LogFile = BeginScriptLogging -ScriptName $ScriptName

Write-Log -Message "Started at: $(Get-FormattedDate)" -LEVEL INFO -Log $LogFile

if(-not (Get-VMSwitch))
{
    Write-Log -Message "No VM Switch detected; quitting" -LEVEL ERROR -Log $LogFile
    Stop-Transcript
    exit 1
}

Set-Location $PSScriptRoot
.\BuildBaseVMTemplate\BuildBaseVMTemplate.ps1 -VMName $VMName -SourceISOPath $sourceIsoPath -autounattendIsoPath $autounattendIsoPath -autounattendXmlIsoPath $autounattendXmlIsoPath -vhdxPath $vhdxPath -vhdxSizeGB $vhdxSizeGB -ramGB $ramGB -cpuCount $cpuCount -productKey $productKey -adminPassword $adminPassword -autounattendXmlFile $autounattendXmlFile -isoOutputDir $isoOutputDir -openVmConnectionWindow $openVmConnectionWindow


Set-Location $PSScriptRoot

function WaitForVmToBootCycle([int]$maxSeconds = 1200)
{
    # During Windows Server install, the VM restarts a few times, so even when the installation waits for the VM's heartbeat to start, the heartbeat starts during setup, followed by a restart
    # This block is here to handle the restart cycles
    $invert = $false
    $cycles = 0
    $installCycles = 3
    $i = 0
    $result = $null
    while($i -lt $maxSeconds)
    {
        $status = ((Get-VMIntegrationService -VMName $VMName | Where-Object {$_.Name -eq "Heartbeat"}).PrimaryStatusDescription)
        if(($result = (($status -eq "OK") -xor $invert)))
        {
            Write-Host "Cycle $($cycles+1)/$installCycles of VM ISO install done"
            $invert = -not $invert
            $cycles++
            if($installCycles -eq $cycles) {
                break
            }
        }
    
        Start-Sleep -Seconds 1
        $i++
    }
    
    if(-not $result)
    {
        throw "Max attempts reached"
        exit 1
    }
}

$bootTime = 600 # seconds
WaitForVmToBootCycle
Write-Log -Message "Waiting for VM to boot for $bootTime seconds" -LEVEL INFO -Log $LogFile
Start-Sleep -Seconds $bootTime
Write-Log -Message "Copying files to VM" -LEVEL INFO -Log $LogFile
Set-Location $PSScriptRoot
.\CopyBuildFilesToVM.ps1 -VMName $VMName
Write-Log -Message "Installing .NET 3.5 from ISO" -LEVEL INFO -Log $LogFile
Set-Location $PSScriptRoot
.\InstallDotNet35FromISO.ps1 -VMName $VMName -adminPassword $adminPassword -Log $logFile
Write-Log -Message "Ejecting ISOs" -LEVEL INFO -Log $LogFile
Get-VMDvdDrive -VMName $VMName | Remove-VMDvdDrive

Write-Log -Message "Removing recovery partition" -LEVEL INFO -Log $LogFile
Set-Location $PSScriptRoot
.\DeleteRecoveryPartition.ps1 -VMName $VMName -adminPassword $adminPassword
Write-Log -Message "Building VM from its inside started" -Level INFO -Log $LogFile
Set-Location $PSScriptRoot
.\InstallWindowsProgramsAndConfigureSettings.ps1 -VMName $VMName -VMSystemVHDxPath $vhdxPath -adminPassword $adminPassword -computerName $computerName -logFile $logFile

Write-Log -Message "Everything done at $(Get-FormattedDate)" -LEVEL INFO -Log $LogFile

Write-ScriptSuccess -Log $LogFile
