param(
    [Parameter(Mandatory = $true)]
    [string]$VMName,
    [Parameter(Mandatory = $true)]
    [string]$GpuInstanceId,
    [Parameter(Mandatory = $true)]
    [string]$GpuLocationPath
)

Set-Location $PSScriptRoot
.("..\AOFLibrary\AOFLibrary.ps1")

function AssignGpuToVM([string]$VMName, [string]$GpuInstanceId, [string]$GpuLocationPath)
{
    if((IsGpuAlreadyAssigned -GpuLocationPath $GpuLocationPath)) 
    {
        throw "The device at $GpuLocationPath is not available to be assigned, it has already been assigned to this or another VM"
    }

    $VM = Get-VM -Name $VMName 

    if($VM.State -ne 'Off')
    {
        throw "VM $VMName is not off"
    }

    if((!$VM.GuestControlledCacheTypes) -or ($VM.AutomaticStopAction -ne "TurnOff") -or ($VM.HighMemoryMappedIoSpace -lt 16GB) -or ($VM.DynamicMemoryEnabled))
    {
        throw "VM $VMName is configured incorrectly"
    }

    try 
    {
        Disable-PnpDevice -InstanceId $GpuInstanceId -Confirm:$false -ErrorAction Stop -Verbose
        Dismount-VMHostAssignableDevice -LocationPath $GpuLocationPath -Force -Verbose
        Add-VMAssignableDevice -LocationPath $GpuLocationPath -VMName $VMName -Verbose        
    }
    catch 
    {
        throw "Assigning a GPU at $GpuLocationPath to $($VM.Name) failed, the GPU might be dismounted from the hypervisor already"
    }
}

AssignGpuToVM -VMName $VMName -GpuInstanceId $GpuInstanceId -GpuLocationPath $GpuLocationPath