<#
.SYNOPSIS
    A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
    A longer description of the function, its purpose, common use cases, etc.
.NOTES
    Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
    Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
    Test-MyTestFunction -Verbose
    Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>

function New-ITDVMwareVMSnapshotTaskV3 {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string[]]
        $VMName,

        [Parameter(Mandatory = $true)]
        [string]
        $Name,

        [string]
        $Description,

        [datetime]
        $DateTime,

        [string[]]
        $Email
    )
    
    begin {
        
    }
    
    process {
        Write-Verbose -Message "Start Loop"
        ForEach ($VName in $VMName) {
            Write-Verbose -Message "Start $VMName"
            $VM = $null

            
            $VM = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } -ErrorAction SilentlyContinue
            If ($VM) {
                $ViServer = $VM.Uid.split('@')[1].split(':')[0]

                $NewSnapshotParams = @{
                    Name     = $Name;
                    RunAsync = $true;
                }
                switch ($PSBoundParameters.Keys) {
                    Description {
                        $NewSnapshotParams.Description = $Description
                    }
                    Memory {
                        $NewSnapshotParams.Memory = $Memory;
                        $NewSnapshotParams.RunAsync = $false;
                    }
                }
                
                Write-Verbose -Message ("Validate DateTime is in the future")
                
                If ($DateTime -lt (Get-Date)) {
                    Write-Warning -Message "DateTime is in the past, recursively running the function again, adjusting start time to 60 seconds from now."
                    $NewITDVMwareVMSnapshotTaskParams = @{
                        VMName      = $VMName;
                        Name        = $Name;
                        Description = $Description;
                        DateTime    = (Get-Date).AddSeconds(60);
                        Email       = ($Email -join ',');
                    }
                    New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams
                }
                else {
                    Write-Verbose -Message ("Attempt sched task creation")
                    try {
                        $si = Get-View ServiceInstance -Server $VIServer
                        $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer
    
                        $spec = New-Object VMware.Vim.ScheduledTaskSpec
                        $spec.Name = $Name, $VName -join '_'
                        $spec.Description = "$Description"
                        $spec.Enabled = $true
                        switch ($PSBoundParameters.Keys) {
                            Email {
                                $spec.Notification = $Email
                            }
                        }
                    
                        $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
                        $spec.Scheduler.runat = $DateTime
                    
                        $spec.Action = New-Object VMware.Vim.MethodAction
                        $spec.Action.Name = "CreateSnapshot_Task"
                    
                        $Memory = $false
                        $Quiesce = $false
    
                        @($Name, $Description, $Memory, $Quiesce) | ForEach-Object {
                            $arg = New-Object VMware.Vim.MethodActionArgument
                            $arg.Value = $_
                            $spec.Action.Argument += $arg
                        }
                        Start-Sleep -Seconds 20
    
                        try {
                            $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)
                        }
                        catch [System.Management.Automation.MethodInvocationException] {
                            Write-Warning -Message "System.Management.Automation.MethodInvocationException"
                            If ($error[0].Exception.Message -like "*You have attempted to schedule the scheduler at a time value*" -and $error[0].Exception.Message -Like "* in the past,*") {
                                Write-Warning -Message "DateTime is in the past, recursively running the function again, adjusting start time to 60 seconds in the future from now."
                                $NewITDVMwareVMSnapshotTaskParams = @{
                                    VMName      = $VMName; 
                                    Name        = $Name;
                                    Description = $Description;
                                    DateTime    = (Get-Date).AddSeconds(60);
                                    Email       = $Email;
                                }
                                New-ITDVMwareVMSnapshotTaskV3 @NewITDVMwareVMSnapshotTaskParams
                            }
                        }
                        catch {
                            Write-Warning -Message "Default"
                        }
                        
                    }
                    catch {
                        Write-Error $error[0]
                    }
                }
            }
        }
    }
    
    end {
        
    }
}