FastTrack-ScheduleManagement.psm1

Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue

Function Get-ResponseError {
<#
.SYNOPSIS
    Get-ResponseError converts HtmlWebResponse error to HtmlWebResponseObject for output
.DESCRIPTION
    Get-ResponseError inputs HtmlWebResponse error and converts to HtmlWebResponseObject for output
.PARAMETER
    Response is the error response returned from webrequest
.EXAMPLE
    Get-ResponseError $_.Exception.Response
.INPUTS
    System.Net.HttpWebResponse
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param([System.Net.HttpWebResponse]$Response)
    $streamReader = New-Object System.IO.StreamReader($Response.GetResponseStream())
    $streamReader.BaseStream.Position = 0
    $streamReader.DiscardBufferedData()
    $body = ConvertFrom-Json($streamReader.ReadToEnd())
    if([string]::IsNullOrEmpty($body))
    {
        $body = ConvertFrom-Json("{}")
    }
    Add-Member -InputObject $body -MemberType NoteProperty -Name "StatusCode" -Value $_.Exception.Response.StatusCode
    $body
}

Function Invoke-GetRequest {
<#
.SYNOPSIS
    Call Rest API with input variables to retrieve appropriate response
.DESCRIPTION
    The Invoke-GetRequest cmdlet utilizes the header parameter to perform the REST API call to modify a FastTrack migration. The REST API is defined in the URI parameter and returns the API's webresponse.
.PARAMETER
    Uri as the endpoint HTML address for the REST API
    Headers is a collection of header keys and values required by the API to return results
.EXAMPLE
    $JsonResult = Invoke-GetRequest -Uri ([System.String]::Format("{0}/{1}/DSR/Status/TransactionId/{2}?{3}", $global:CsiApiBaseUriFormat, $TenantId, $TransactionId, $query)) -Headers $header
.INPUTS
    System.String
    System.Collections.Hashtable
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param([String]$Uri, [hashtable]$Headers)
    $response = try {
        Invoke-RestMethod -Method GET -Uri $Uri -ContentType 'application/json' -Headers $Headers
    } catch {
        Get-ResponseError $_.Exception.Response
    }

    return $response
}

Function Invoke-PostRequest {
<#
.SYNOPSIS
    Call Rest API with input variables to retrieve appropriate response
.DESCRIPTION
    The Invoke-PostRequest cmdlet utilizes the body and header parameters to perform the REST API call to modify a FastTrack migration. The REST API is defined in the URI parameter and returns the API's webresponse.
.PARAMETER
    Uri as the endpoint HTML address for the REST API
    Headers is a collection of header keys and values required by the API to return results
    Body is the collected form data required by the API to return results
.EXAMPLE
.INPUTS
    System.String
    System.Collections.Hashtable
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param([String]$Uri, [hashtable]$Headers, [String]$Body)
    $response = try {
    Invoke-RestMethod -Method POST -Uri $Uri -ContentType 'application/json;charset=utf-8'  -Headers $Headers -Body ([System.Text.Encoding]::UTF8.GetBytes($Body))
    } catch {
    Get-ResponseError $_.Exception.Response
    }

    return $response
}

Function Invoke-PutRequest {
<#
.SYNOPSIS
    Call Rest API with input variables to retrieve appropriate response
.DESCRIPTION
    The Invoke-PutRequest cmdlet utilizes the body and header parameters to perform the REST API call to modify a FastTrack migration. The REST API is defined in the URI parameter and returns the API's webresponse.
.PARAMETER
    Uri as the endpoint HTML address for the REST API
    Headers is a collection of header keys and values required by the API to return results
    Body is the collected form data required by the API to return results
.EXAMPLE
.INPUTS
    System.String
    System.Collections.Hashtable
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param([String]$Uri, [hashtable]$Headers, [String]$Body)
    $response = try {
    Invoke-RestMethod -Method PUT -Uri $Uri -ContentType 'application/json' -Headers $Headers -Body $Body
    } catch {
    Get-ResponseError $_.Exception.Response
    }

    return $response
}

Function Invoke-DeleteRequest {
<#
.SYNOPSIS
    Deletes Transaction
.DESCRIPTION
    The Invoke-DeleteRequest cmdlet utilizes the body and header parameters to perform the REST API call to delete a FastTrack migration. The REST API is defined in the URI parameter and returns the API's webresponse.
.PARAMETER
    Uri as the endpoint HTML address for the REST API
    Headers is a collection of header keys and values required by the API to return results
    Body is the collected form data required by the API to return results
.EXAMPLE
    $JsonResult = Invoke-DeleteRequest -Uri ([System.String]::Format("{0}KeyVault",$global:CsiApiBaseUriFormat)) -Headers $header -Body $serializedJson
.INPUTS
    System.String
    System.Collections.Hashtable
.OUTPUTS
    HtmlWebResponseObject
.LINK
#>

    param([String]$Uri, [hashtable]$Headers, [String]$Body)
    $response = try {
    Invoke-RestMethod -Method DELETE -Uri $Uri -ContentType 'application/json' -Headers $Headers -Body $Body
    } catch {
    Get-ResponseError $_.Exception.Response
    }

    return $response
}

Function Waiting-TransactionComplete() {
<#
.SYNOPSIS
    Find status of Transaction
.DESCRIPTION
    The Waiting-TransactionComplete cmdlet calls Get-FastTrackMigrationStatus repetatively while migration is not complete or not failed. When the transaction has completed or failed, Waiting-TransactionComplete returns the transaction object to caller.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackMigrationAccount cmdlet.
.PARAMETER
    TransactionId is the GUID representing the specified transaction
.EXAMPLE
    Waiting-TransactionComplete -TransactionID ($JsonResult.TransactionId)
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates System.Management.Automation.PSObject object that represents transaction ID.
.LINK
#>

    param([string] $TransactionID = $(throw "Transaction ID unable to find, Please try again."))

    [array]$FinalResults = "Completed","Failed"

    $current = $previous = 1;
    do {
        $Transaction = Get-FastTrackMigrationTransactionStatus -TransactionID $TransactionID

        for ($j = 1; (!$FinalResults.Contains($Transaction.Status) -and $j -le $current); $j++) {
            sleep -Milliseconds 1000
            Write-Progress -Id 1 -Activity Waiting -Status 'Next attempt will start ' -PercentComplete ($j/$current*100) -SecondsRemaining ($current-$j)
        }
        $current,$previous = ($current + $previous),$current

    } while ($current -lt 60 -and !$FinalResults.Contains($Transaction.Status))
    return $Transaction
}

Function SetIdentityRecipientValues {
<#
.SYNOPSIS
    Set recipient identity
.DESCRIPTION
     The SetIdentityRecipientValues cmdlet, intended for Global Administrators, to create an identity-object from input parameters. This new identity is returned to caller.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackMigrationAccount cmdlet.
.EXAMPLE
    $CustomerIdentity = SetIdentityRecipientValues
.INPUTS
    None
.OUTPUTS
    PSObject Identity
.LINK
#>

    [string] $TenantID =  $global:MsoAdminProperties['MSO-CompanyTenantInfo']
    [string] $CompanyName = $global:MsoAdminProperties["MSO-CompanyInfo"].DisplayName
    [string] $LogonUserEmail = $global:MsoAdminProperties["MSO-LoggedOnUser"].Account

    $Identity = (New-Object PSObject |
        Add-Member -PassThru NoteProperty TenantId $TenantID |
        Add-Member -PassThru NoteProperty CompanyName $CompanyName |
        Add-Member -PassThru NoteProperty LogonUserEmail $LogonUserEmail)

    return $Identity
}

Function SetCreateRequestValues {
<#
.SYNOPSIS
    Set recipient request
.DESCRIPTION
     The SetCreateRequestValues cmdlet, intended for Global Administrators, to create a customer-object from input parameters that are used to define details to be used in REST API calls to create a FastTrack migration schedule.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackMigrationAccount cmdlet.
.PARAMETER Tenant ID for customer request
.PARAMETER Company name for customer request
.PARAMETER User email used for customer login
.PARAMETER MigrationType
    Type of migration.
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExStaged
        Staged Migration
    Mig-ExCutover
        Cutover Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleSites
        GoogleSites Migration
    MIG-SPOnPrem
        SP On Prem Migration
.PARAMETER Source
    Source for different migration types.
.PARAMETER Target
    Target for different migration types.
.PARAMETER MigrationDate
    Date of migration.
.PARAMETER MigrationWindow
    Migration event window.
.PARAMETER MigrationGroup
    Migration group.
.PARAMETER Size
    Size of source storage.
.PARAMETER IsCutover
    Is cutover true | false | null.
.PARAMETER Region
    Name of region.
.PARAMETER PropertyBag
.EXAMPLE
    $jsonObj = SetCreateRequestValues -RecipientId $RecipientId -FirstName $FirstName -LastName $LastName -EmailAddress $EmailAddress -Description $Description
.INPUTS
    System.String
.OUTPUTS
    PSObject CustomerObject
.LINK
#>

    param
    (
        [string] $TenantID,
        [string] $CompanyName,
        [string] $LogonUserEmail,
        [string] $MigrationType,
        [string] $Source,
        [string] $Target,
        [string] $MigrationDate,
        [string] $MigrationWindow,
        [string] $MigrationGroup,
        [string] $Size,
        [string] $PropertyBag,
        [string] $IsCutover,
        [string] $Region

    )

        $CustomerIdentity = (New-Object PSObject |
        Add-Member -PassThru NoteProperty TenantId $TenantID |
        Add-Member -PassThru NoteProperty CompanyName $CompanyName |
        Add-Member -PassThru NoteProperty LogOnUserEmail $LogonUserEmail)

        $CustomerObject = (New-Object PSObject |
        Add-Member -PassThru NoteProperty Customer $CustomerIdentity |
        Add-Member -PassThru NoteProperty MigrationType $MigrationType |
        Add-Member -PassThru NoteProperty Source $Source |
        Add-Member -PassThru NoteProperty Target $Target |
        Add-Member -PassThru NoteProperty MigrationDate $MigrationDate |
        Add-Member -PassThru NoteProperty MigrationWindow $MigrationWindow |
        Add-Member -PassThru NoteProperty MigrationGroup $MigrationGroup |
        Add-Member -PassThru NoteProperty Size $Size |
        Add-Member -PassThru NoteProperty IsCutover $IsCutover |
        Add-Member -PassThru NoteProperty Region $Region |
        Add-Member -PassThru NoteProperty PropertyBag $PropertyBag |
        Add-Member -PassThru NoteProperty TransactionId "00000000-0000-0000-0000-000000000000" |
        Add-Member -PassThru NoteProperty ScheduleIdentifier "00000000-0000-0000-0000-000000000000" |
        Add-Member -PassThru NoteProperty EnvironmentType $global:MsoComOrGov )

        return $CustomerObject
}

Function SetUpdateRequestValues {
<#
.SYNOPSIS
    Update recipient request
.DESCRIPTION
    The SetUpdateRequestValues cmdlet, intended for Global Administrators, to create a customer-object from input parameters that are used to define details to be used in REST API calls to update migration update details.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackMigrationAccount cmdlet.
.PARAMETER Tenant ID for customer request
.PARAMETER Company name for customer request
.PARAMETER User email used for customer login
.PARAMETER MigrationType
    Type of migration.
        Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExStaged
        Staged Migration
    Mig-ExCutover
        Cutover Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleSites
        GoogleSites Migration
    MIG-SPOnPrem
        SP On Prem Migration
.PARAMETER Source
    Source for different migration types.
.PARAMETER Target
    Target for different migration types.
.PARAMETER MigrationDate
    Date of migration.
.PARAMETER MigrationWindow
    Migration event window.
.PARAMETER MigrationGroup
    Migration group.
.PARAMETER Size
    Size of source storage.
.PARAMETER IsCutover
    Is cutover true | false | null.
.PARAMETER Region
    Name of region.
.PARAMETER PropertyBag
.EXAMPLE
    $jsonObj = SetUpdateRequestValues -RecipientId $RecipientId -FirstName $FirstName -LastName $LastName -EmailAddress $EmailAddress -Description $Description
.INPUTS
    System.String
.OUTPUTS
    PSObject CustomerObject
.LINK
#>

    param
    (
        [string] $TenantID,
        [string] $CompanyName,
        [string] $LogonUserEmail,
        [string] $MigrationType,
        [string] $Source,
        [string] $Target,
        [string] $MigrationDate,
        [string] $MigrationWindow,
        [string] $MigrationGroup,
        [string] $Size,
        [string] $PropertyBag,
        [string] $IsCutover,
        [string] $Region
    )

        $CustomerIdentity = (New-Object PSObject |
        Add-Member -PassThru NoteProperty TenantId $TenantID |
        Add-Member -PassThru NoteProperty CompanyName $CompanyName |
        Add-Member -PassThru NoteProperty LogOnUserEmail $LogonUserEmail)

        $CustomerObject = (New-Object PSObject |
        Add-Member -PassThru NoteProperty Customer $CustomerIdentity |
        Add-Member -PassThru NoteProperty TransactionId "00000000-0000-0000-0000-000000000000" |
        Add-Member -PassThru NoteProperty MigrationType $MigrationType |
        Add-Member -PassThru NoteProperty Source $Source |
        Add-Member -PassThru NoteProperty Target $Target |
        Add-Member -PassThru NoteProperty MigrationDate $MigrationDate |
        Add-Member -PassThru NoteProperty MigrationWindow $MigrationWindow |
        Add-Member -PassThru NoteProperty MigrationGroup $MigrationGroup |
        Add-Member -PassThru NoteProperty Size $Size |
        Add-Member -PassThru NoteProperty IsCutover $IsCutover |
        Add-Member -PassThru NoteProperty Region $Region |
        Add-Member -PassThru NoteProperty PropertyBag $PropertyBag |
        Add-Member -PassThru NoteProperty EnvironmentType $global:MsoComOrGov )

        return $CustomerObject
}

Function GetObjectFromSchedule {
<#
.SYNOPSIS
    Get Schedule
.DESCRIPTION
    The GetObjectFromSchedule cmdlet is intended to convert the input Schedule parameter into a powershell custom schedule-object. The created custom object is returned to caller.
.PARAMETER Schedule as input object from HtmlWebResponseObject
.EXAMPLE
    $result += GetObjectFromSchedule -Schedule $sch
.INPUTS
    HtmlWebResponseObject
.OUTPUTS
    PSObject
.LINK
#>

    param ($Schedule)
    $newObject = New-Object -Typename PSCustomObject -Property @{
        MigrationType = $Schedule.MigrationType
        Source = $Schedule.Source
        Target = $Schedule.Target
        MigrationDate = $Schedule.MigrationDate
        MigrationWindow = $Schedule.MigrationWindow
        MigrationGroup = $Schedule.MigrationGroup
        Region = $Schedule.Region
        Size = $Schedule.Size
        ScheduleUserId = $Schedule.ScheduleUserId
        ScheduleStatus = $Schedule.ScheduleStatus
    }

    if($Schedule.PropertyBag -ne $null)
    {
        $prop = ConvertFrom-Json $Schedule.PropertyBag
        $prop.PSObject.Properties | ForEach-Object {
            if($myObject.PSobject.Properties.Name -contains "Name" -or $myObject.PSobject.Properties.Name -contains "Value")
            {
                $newObject | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value
            }
        }
    }
    
    return $newObject
}

Function SetPropertyBag {
<#
.SYNOPSIS
    The SetPropertyBag cmdlet uses the MigrationType parameter and appropriate input values, dependent on the type of migration defined. The, newly defined, property bag is converted into a json-object and returned to the caller.
.DESCRIPTION
    This cmdlet to create a new PropertyBag.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.PARAMETER MigrationType
    Type of migration.
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExCutover
        Cutover Migration
    Mig-ExStaged
        Staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GoogleSites
        GoogleSites Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    MIG-SPOnPrem
        Sharepoint Migration
.EXAMPLE
    $PropertyBag = SetPropertyBag -MigrationType $MigrationType
.INPUTS
    System.String
.OUTPUTS
    PSObject PropertyBag
.LINK
#>

    param
    (
        [string] $MigrationType
    )

    if ($MigrationType -eq "Mig-ExHybrid" -or $MigrationType -eq "Mig-ExSimpleMRS" -or $MigrationType -eq "Mig-ExCutover" -or $MigrationType -eq "Mig-ExStaged")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty MigrationEndpoint $MigrationEndpoint.Value)
    }
    elseif ($MigrationType -eq "Mig-FileSharesToOneDrive")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty Office365UPNAccount $Office365UPNAccount.Value |
                    Add-Member -PassThru NoteProperty TargetDocumentLibrary $TargetDocumentLibrary.Value |
                    Add-Member -PassThru NoteProperty FileCount $FileCount.Value)
    }
    elseif ($MigrationType -eq "Mig-FileSharesToTeamSites")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty TargetSharePointSite $TargetSharePointSite.Value |
                    Add-Member -PassThru NoteProperty TargetDocumentLibrary $TargetDocumentLibrary.Value |
                    Add-Member -PassThru NoteProperty FileCount $FileCount.Value)
    }
    elseif ($MigrationType -eq "Mig-Domino-BAM")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty O365UsageLocation $O365UsageLocation.Value |
                    Add-Member -PassThru NoteProperty O365DisplayName $O365DisplayName.Value |
                    Add-Member -PassThru NoteProperty LicenseSubscriptionID $LicenseSubscriptionID.Value |
                    Add-Member -PassThru NoteProperty InPlaceHoldIdentity $InPlaceHoldIdentity.Value |
                    Add-Member -PassThru NoteProperty HasBlackBerry $HasBlackBerry.Value |
                    Add-Member -PassThru NoteProperty VIP $VIP.Value |
                    Add-Member -PassThru NoteProperty DominoBESServer $DominoBESServer.Value |
                    Add-Member -PassThru NoteProperty SecondPassEmailAddress $SecondPassEmailAddress.Value)
    }
    elseif ($MigrationType -eq "Mig-Box" -or $MigrationType -eq "Mig-GoogleDrive")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty FilesOwned $FilesOwned.Value)
    }
    elseif ($MigrationType -eq "Mig-Domino-ODME")
    {
        $PropertyBagObj = (New-Object PSObject |
            Add-Member -PassThru NoteProperty O365UsageLocation $O365UsageLocation.Value |
            Add-Member -PassThru NoteProperty O365DisplayName $O365DisplayName.Value |
            Add-Member -PassThru NoteProperty LotusNotesName $LotusNotesName.Value |
            Add-Member -PassThru NoteProperty Location $Location.Value |
            Add-Member -PassThru NoteProperty Resource $Resource.Value  )
    }
    elseif ($MigrationType -eq "Mig-IMAP")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty Password $Password.Value)
    }
    elseif ($MigrationType -eq "Mig-GroupWise")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty PoHostingTheMailbox $PoHostingTheMailbox.Value |
                    Add-Member -PassThru NoteProperty SoapPort $SoapPort.Value)
    }
        elseif ($MigrationType -eq "Mig-GoogleSites")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty Hold $Hold.Value)
    }
    elseif ($MigrationType -eq "MIG-SPOnPrem")
    {
        $PropertyBagObj = (New-Object PSObject |
                    Add-Member -PassThru NoteProperty Hold $Hold.Value)
    }
    else { }
    return ($PropertyBagObj | ConvertTo-Json -Compress: $true)
}

Function Get-CsvAsJson {
<#
.SYNOPSIS
    Read CSV file contents
.DESCRIPTION
    The Get-CsvAsJson cmdlet reads an input CSV file contents, converting the individual elements of data into a json-compatible object which is returned to the caller.
.PARAMETER File path to csv file for input
.EXAMPLE
    $FileContentStr = Get-CsvAsJson -FilePath $FilePath
.INPUTS
    System.String
.OUTPUTS
    Json object
.LINK
#>

    param
    (
        [string] $FilePath
    )
    [string] $targetBaseUrl = ""

    $readData = Get-Content $FilePath -Encoding UTF8 | ForEach-Object {
        #csv is FileShareManager
        [string] $line = $_.ToString().ToLower()
        $lineNumber++
        if($targetBaseUrl -eq "")
        {
            [int] $index = $line.IndexOf("https://")
            if($index -gt 0)
            {
                $indexOfComma = $line.IndexOf(',', $index)
                if($indexOfComma -le 0){
                    $indexOfComma = line.Length;
                }
                $targetBaseUrl = $line.Substring($index, $indexOfComma - $index).TrimEnd('/');
                $targetBaseUrl += "/";
            }
        }
        else
        {
            if($line -match '^([,"]+|[\s]*$)')
            {
                if(!$endLine)
                {
                    $endLine = $lineNumber
                }
            }
        }
    }

    if($targetBaseUrl -ne "") #If csv is FileShareManager
    {
        $FileContent =  Get-Content $FilePath -Encoding UTF8 | select -Skip 1 -First ($endLine-2) | Out-String | ConvertFrom-Csv
        foreach ($obj in $FileContent)
        {
            $obj."Target SharePoint Site" = $targetBaseUrl + $obj."Target SharePoint Site"
        }
    }
    else
    {
        $FileContent = Get-Content $FilePath -Encoding UTF8 | Out-String | ConvertFrom-Csv
    }

    if($FileContent -isnot [Array])    {
        #csv contails single row
        $FileContentStr = $FileContent | ConvertTo-Json -Compress: $true
        $FileContentStr = "[" + $FileContentStr + "]"
    }
    else {
        $FileContentStr = $FileContent | ConvertTo-Json -Compress: $true
    }

    return $FileContentStr
}

Function Get-FastTrackMigrationSchedule {
<#
.SYNOPSIS
    Get FastTrack schedule list.
.DESCRIPTION
    The Get-FastTrackMigrationSchedule cmdlet invokes the REST API to retrieve the FastTrack migration schedule for the input ScheduleUserId parameter. Retrieved scheduled migrations are input to an array of schedules adn returned to the caller.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.PARAMETER ScheduleUserId
    Unique Guid for FastTrack schedule.
.EXAMPLE
    Get-FastTrackMigrationSchedule -ScheduleUserId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the list of FastTrack schedule details.
.LINK
    New-FastTrackMigrationSchedule
    Set-FastTrackMigrationSchedule
    Remove-FastTrackMigrationSchedule
    New-FastTrackMigrationScheduleFromCsv
    Get-FastTrackMigrationDeleteTypes
#>

    param
    (
        [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
        [alias("ScheduleId")]
        [string] $ScheduleUserId
    )
    try
    {
        if($global:MsoAdminProperties.Count -eq 0)
        {
            Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
            return
        }

        [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

        $header = @{}
        if($global:v2FeatureFlag -eq $true){
        $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
        else{
        $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
        $header.Add("TENANT_ID",$TenantId)
        Write-Host "Sending Schedule Get Request..."

        $query += "environmentType=$global:MsoComOrGov"

        if (!$ScheduleUserId)
        {
            $requestUri = [System.String]::Format("{0}{1}/Schedule?$($query)", $global:CsiApiBaseUriFormat, $TenantId)
        }
        else
        {
            try {
                $isError = [GUID]::Parse($ScheduleUserId)
            }
            catch {
                Write-Warning "ScheduleUserId is not a valid GUID format. To obtain the ScheduleUserId , please run 'Get-FastTrackMigrationSchedule' to retrieve a list of all schedules."
                return
            }
            $requestUri = [System.String]::Format("{0}{1}/Schedule/{2}?$($query)", $global:CsiApiBaseUriFormat, $TenantId, $ScheduleUserId)
        }

        $JsonResult = Invoke-GetRequest -Uri ([System.String]::Format($requestUri, $TenantId, $ScheduleUserId)) -Headers $header

        if($JsonResult.StatusCode -ne $null)
        {
            # Error?
            Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
        }
        else
        {
            Write-Host "Get request completed"
            if ($JsonResult.Schedules)
            {
                $result = @()
                foreach($sch in $JsonResult.Schedules)
                {
                    $result += GetObjectFromSchedule -Schedule $sch
                }
                return $result
            }
        }
        return (GetObjectFromSchedule -Schedule $JsonResult)
    }
    catch
    {

        Write-Warning -Message:"An error occurred attempting to authenticate with this module"
        Write-Warning -Message: $_.Exception.Message
        Write-Host "Press the [enter] key to close this process"
        Read-Host
    }
}

Function New-FastTrackMigrationSchedule {
<#
.SYNOPSIS
    Creates a new FastTrack schedule.
.DESCRIPTION
    The New-FastTrackMigrationSchedule cmdlet invokes the REST API to create a new FastTrack migration schedule. The Waiting-TransactionComplete cmdlet is invoked to return the "completed" or "failed" status of the migration transaction invoked.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.PARAMETER MigrationType
    Type of migration.
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExCutover
        Cutover Migration
    Mig-ExStaged
        Staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GoogleSites
        GoogleSites Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    MIG-SPOnPrem
        Sharepoint Migration
.PARAMETER Source
    Source for different migration types.
.PARAMETER Target
    Target for different migration types.
.PARAMETER MigrationDate
    Date of migration.
.PARAMETER MigrationWindow
    Migration event window.
.PARAMETER MigrationGroup
    Migration group.
.PARAMETER Size
    Size of source storage.
.PARAMETER IsCutover
    Is cutover true | false | null.
.PARAMETER Region
    Name of region.
.EXAMPLE
    New-FastTrackMigrationSchedule -MigrationType "Mig-Box" -Source "joe@contoso.com" -Target "Jane@contoso.net" -MigrationDate "YYYY-DD-MMTHH:MIN:SS" -MigrationWindow "Window1" -MigrationGroup "Group1" -Size 2 -PropertyBag "FilesOwned"
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the Transaction ID .
.LINK
    Get-FastTrackMigrationSchedule
    Remove-FastTrackMigrationSchedule
    Set-FastTrackMigrationSchedule
    New-FastTrackMigrationScheduleFromCsv
    Get-FastTrackMigrationDeleteTypes
#>

    [cmdletbinding()]
    param(
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)]
            [ValidateSet("Mig-ExHybrid","Mig-ExSimpleMRS","Mig-ExCutover","Mig-ExStaged","Mig-IMAP","Mig-GmailCutover","Mig-GmailStaged","Mig-GroupWise","Mig-GoogleDrive","Mig-GoogleSites","Mig-Box","Mig-FileSharesToOneDrive","Mig-FileSharesToTeamSites","Mig-Domino-BAM","Mig-Domino-ODME","MIG-SPOnPrem")]
            [string] $MigrationType,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $Source,
            [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
            [string] $Target,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationDate,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationWindow,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationGroup,
            [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
            [string] $Size = 0,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $Region
        )

    DynamicParam
    {
        if($MigrationType) {
            $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        }

        if ($MigrationType -eq "Mig-ExHybrid" -or $MigrationType -eq "Mig-ExSimpleMRS" -or $MigrationType -eq "Mig-ExCutover" -or $MigrationType -eq "Mig-ExStaged") {
            $EpAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $IscutoverAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($EpAttribute)
            $attributeCollection2.Add($IscutoverAttribute)

            $MigrationEndpoint = New-Object System.Management.Automation.RuntimeDefinedParameter('MigrationEndpoint', [String], $attributeCollection1)
            $paramDictionary.Add('MigrationEndpoint', $MigrationEndpoint)

            $IsCutover = New-Object System.Management.Automation.RuntimeDefinedParameter('IsCutover', [Nullable[boolean]], $attributeCollection2)
            $paramDictionary.Add('IsCutover', $IsCutover)
        }
        elseif ($MigrationType -eq "Mig-FileSharesToOneDrive") {
            $Office365UPNAccountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $TargetDocumentLibraryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $FileCountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($Office365UPNAccountAttribute)
            $attributeCollection2.Add($TargetDocumentLibraryAttribute)
            $attributeCollection3.Add($FileCountAttribute)

            $Office365UPNAccount = New-Object System.Management.Automation.RuntimeDefinedParameter('Office365UPNAccount', [String], $attributeCollection1)
            $paramDictionary.Add('Office365UPNAccount', $Office365UPNAccount)

            $TargetDocumentLibrary = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetDocumentLibrary', [String], $attributeCollection2)
            $paramDictionary.Add('TargetDocumentLibrary', $TargetDocumentLibrary)

            $FileCount = New-Object System.Management.Automation.RuntimeDefinedParameter('FileCount', [String], $attributeCollection3)
            $paramDictionary.Add('FileCount', $FileCount)
        }
        elseif ($MigrationType -eq "Mig-FileSharesToTeamSites") {
            $TargetSharePointSiteAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $TargetDocumentLibraryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $FileCountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($TargetSharePointSiteAttribute)
            $attributeCollection2.Add($TargetDocumentLibraryAttribute)
            $attributeCollection3.Add($FileCountAttribute)

            $TargetSharePointSite = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetSharePointSite', [String], $attributeCollection1)
            $paramDictionary.Add('TargetSharePointSite', $TargetSharePointSite)

            $TargetDocumentLibrary = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetDocumentLibrary', [String], $attributeCollection2)
            $paramDictionary.Add('TargetDocumentLibrary', $TargetDocumentLibrary)

            $FileCount = New-Object System.Management.Automation.RuntimeDefinedParameter('FileCount', [String], $attributeCollection3)
            $paramDictionary.Add('FileCount', $FileCount)
        }
        elseif ($MigrationType -eq "Mig-Domino-BAM") {
            $O365UsageLocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $O365DisplayNameAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LicenseSubscriptionIDAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $InPlaceHoldIdentityAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $HasBlackBerryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $VIPAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $DominoBESServerAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $SecondPassEmailAddressAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection4 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection5 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection6 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection7 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection8 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($O365UsageLocationAttribute)
            $attributeCollection2.Add($O365DisplayNameAttribute)
            $attributeCollection3.Add($LicenseSubscriptionIDAttribute)
            $attributeCollection4.Add($InPlaceHoldIdentityAttribute)
            $attributeCollection5.Add($HasBlackBerryAttribute)
            $attributeCollection6.Add($VIPAttribute)
            $attributeCollection7.Add($DominoBESServerAttribute)
            $attributeCollection8.Add($SecondPassEmailAddressAttribute)

            $O365UsageLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('O365UsageLocation', [String], $attributeCollection1)
            $paramDictionary.Add('O365UsageLocation', $O365UsageLocation)

            $O365DisplayName = New-Object System.Management.Automation.RuntimeDefinedParameter('O365DisplayName', [String], $attributeCollection2)
            $paramDictionary.Add('O365DisplayName', $O365DisplayName)

            $LicenseSubscriptionID = New-Object System.Management.Automation.RuntimeDefinedParameter('LicenseSubscriptionID', [String], $attributeCollection3)
            $paramDictionary.Add('LicenseSubscriptionID', $LicenseSubscriptionID)

            $InPlaceHoldIdentity = New-Object System.Management.Automation.RuntimeDefinedParameter('InPlaceHoldIdentity', [String], $attributeCollection4)
            $paramDictionary.Add('InPlaceHoldIdentity', $InPlaceHoldIdentity)

            $HasBlackBerry = New-Object System.Management.Automation.RuntimeDefinedParameter('HasBlackBerry', [String], $attributeCollection5)
            $paramDictionary.Add('HasBlackBerry', $HasBlackBerry)

            $VIP = New-Object System.Management.Automation.RuntimeDefinedParameter('VIP', [String], $attributeCollection6)
            $paramDictionary.Add('VIP', $VIP)

            $DominoBESServer = New-Object System.Management.Automation.RuntimeDefinedParameter('DominoBESServer', [String], $attributeCollection7)
            $paramDictionary.Add('DominoBESServer', $DominoBESServer)

            $SecondPassEmailAddress = New-Object System.Management.Automation.RuntimeDefinedParameter('SecondPassEmailAddress', [String], $attributeCollection8)
            $paramDictionary.Add('SecondPassEmailAddress', $SecondPassEmailAddress)
        }
        elseif ($MigrationType -eq "Mig-Box" -or $MigrationType -eq "Mig-GoogleDrive") {
            $FilesOwnedAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($FilesOwnedAttribute)
            $FilesOwned = New-Object System.Management.Automation.RuntimeDefinedParameter('FilesOwned', [String], $attributeCollection)
            $paramDictionary.Add('FilesOwned', $FilesOwned)
        }
        elseif ($MigrationType -eq "Mig-Domino-ODME") {
            $O365UsageLocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $O365DisplayNameAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LotusNotesNameAttribute  = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $ResourceAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection4 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection5 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($O365UsageLocationAttribute)
            $attributeCollection2.Add($O365DisplayNameAttribute)
            $attributeCollection3.Add($LotusNotesNameAttribute )
            $attributeCollection4.Add($LocationAttribute)
            $attributeCollection5.Add($ResourceAttribute)

            $O365UsageLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('O365UsageLocation', [String], $attributeCollection1)
            $paramDictionary.Add('O365UsageLocation', $O365UsageLocation)

            $O365DisplayName = New-Object System.Management.Automation.RuntimeDefinedParameter('O365DisplayName', [String], $attributeCollection2)
            $paramDictionary.Add('O365DisplayName', $O365DisplayName)

            $LotusNotesName= New-Object System.Management.Automation.RuntimeDefinedParameter('LotusNotesName', [String], $attributeCollection3)
            $paramDictionary.Add('LotusNotesName', $LotusNotesName )

            $Location = New-Object System.Management.Automation.RuntimeDefinedParameter('Location', [String], $attributeCollection4)
            $paramDictionary.Add('Location', $Location)

            $Resource = New-Object System.Management.Automation.RuntimeDefinedParameter('Resource', [String], $attributeCollection5)
            $paramDictionary.Add('Resource', $Resource)
        }
        elseif ($MigrationType -eq "Mig-IMAP") {
            $PasswordAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($PasswordAttribute)
            $Password = New-Object System.Management.Automation.RuntimeDefinedParameter('Password', [String], $attributeCollection)
            $paramDictionary.Add('Password', $Password)
        }
        elseif ($MigrationType -eq "Mig-GroupWise") {
            $PoHostingTheMailboxAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $SoapPortAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($PoHostingTheMailboxAttribute)
            $attributeCollection2.Add($SoapPortAttribute)

            $PoHostingTheMailbox = New-Object System.Management.Automation.RuntimeDefinedParameter('PoHostingTheMailbox', [String], $attributeCollection1)
            $paramDictionary.Add('PoHostingTheMailbox', $PoHostingTheMailbox)

            $SoapPort = New-Object System.Management.Automation.RuntimeDefinedParameter('SoapPort', [String], $attributeCollection2)
            $paramDictionary.Add('SoapPort', $SoapPort)
        }
        elseif ($MigrationType -eq "Mig-GoogleSites") {
            $HoldAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($HoldAttribute)
            $Hold = New-Object System.Management.Automation.RuntimeDefinedParameter('Hold', [String], $attributeCollection)
            $paramDictionary.Add('Hold', $Hold)
        }
        elseif ($MigrationType -eq "MIG-SPOnPrem") {
            $HoldAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($HoldAttribute)
            $Hold = New-Object System.Management.Automation.RuntimeDefinedParameter('Hold', [String], $attributeCollection)
            $paramDictionary.Add('Hold', $Hold)
        }
        else { }

        if($MigrationType) {
            return $paramDictionary
        }
    }

    Process
    {
        if($global:MsoAdminProperties.Count -eq 0)
        {
            Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
            return
        }
        try
        {
            [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

            $PropertyBag = SetPropertyBag -MigrationType $MigrationType
            $jsonObj = SetCreateRequestValues -TenantID: $TenantId `
                                                -CompanyName: $global:MsoAdminProperties["MSO-CompanyInfo"].DisplayName `
                                                -LogonUserEmail: $global:MsoAdminProperties["MSO-LoggedOnUser"].Account `
                                                -MigrationType: $MigrationType `
                                                -Source: $Source `
                                                -Target: $Target `
                                                -MigrationDate: $MigrationDate `
                                                -MigrationWindow: $MigrationWindow `
                                                -MigrationGroup: $MigrationGroup `
                                                -Size: $Size `
                                                -IsCutover $IsCutover.Value `
                                                -Region $Region `
                                                -PropertyBag: $PropertyBag

            $serializedJson = $jsonObj | ConvertTo-Json -Compress: $true

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID",$TenantId)
            Write-Host "Sending Schedule Create Request..."

            $JsonResult = Invoke-PostRequest -Uri ([System.String]::Format("{0}Schedule/Create",$global:CsiApiBaseUriFormat)) -Headers $header -Body $serializedJson

            if($JsonResult.StatusCode -ne $null)
            {
                # Error?
                Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
            }
            else
            {
                Waiting-TransactionComplete -TransactionID ($JsonResult.TransactionId)
            }
        }
        catch
        {
            Write-Warning -Message: $_.Exception.Message
            Write-Host "Press the [enter] key to close this process"
            Read-Host
        }

    }
}

Function Set-FastTrackMigrationSchedule {
<#
.SYNOPSIS
    Updates an existing FastTrack schedule.
.DESCRIPTION
    The Set-FastTracikMigrationSchedule cmdlet invokes REST API with input ScheduleId parameter. The ScheduleId is used by the API to define the migration schedules to be udpated. The Waiting-TransactionComplete cmdlet is invoked to return the "completed" or "failed" status of the migration transaction invoked.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.PARAMETER ScheduleUserId
    Unique GUID For FastTrack Schedule.
.PARAMETER MigrationType
    Type of migration.
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExCutover
        Cutover Migration
    Mig-ExStaged
        Staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GoogleSites
        GoogleSites Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    MIG-SPOnPrem
        Sharepoint Migration
.PARAMETER Source
    Source for different migration types.
.PARAMETER Target
    Target for different migration types.
.PARAMETER MigrationDate
    Date of migration.
.PARAMETER MigrationWindow
    Migration event window.
.PARAMETER MigrationGroup
    Migration group.
.PARAMETER Size
    Size of source storage
.PARAMETER IsCutover
    Is cutover true | false | null.
.PARAMETER Region
    Name of region.
.PARAMETER PropertyBag
    Properties for different migration types.
.EXAMPLE
    New-FastTrackMigrationSchedule -ScheduleUserId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -MigrationType "Mig-Box" -Source "joe@contoso.com" -Target "Jane@contoso.net" -MigrationDate "YYYY-DD-MMTHH:MIN:SS" -MigrationWindow "Window1" -MigrationGroup "Group1" -Size 2 -PropertyBag "FilesOwned"
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the Transaction ID .
.LINK
    Get-FastTrackMigrationSchedule
    Remove-FastTrackMigrationSchedule
    New-FastTrackMigrationSchedule
    New-FastTrackMigrationScheduleFromCsv
    Get-FastTrackMigrationDeleteTypes
#>

    [cmdletbinding()]
    param(
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)]
            [Alias("ScheduleId")]
            [string] $ScheduleUserId,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=1)]
            [ValidateSet("Mig-ExHybrid","Mig-ExSimpleMRS","Mig-ExCutover","Mig-ExStaged","Mig-IMAP","Mig-GmailCutover","Mig-GmailStaged","Mig-GroupWise","Mig-GoogleDrive","Mig-GoogleSites","Mig-Box","Mig-FileSharesToOneDrive","Mig-FileSharesToTeamSites","Mig-Domino-BAM","Mig-Domino-ODME","MIG-SPOnPrem")]
            [string] $MigrationType,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $Source,
            [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
            [string] $Target,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationDate,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationWindow,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationGroup,
            [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
            [string] $Size = 0,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $Region
        )

    DynamicParam
    {
        if($MigrationType) {
            $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        }

        if ($MigrationType -eq "Mig-ExHybrid" -or $MigrationType -eq "Mig-ExSimpleMRS" -or $MigrationType -eq "Mig-ExCutover" -or $MigrationType -eq "Mig-ExStaged") {
            $EpAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $IscutoverAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($EpAttribute)
            $attributeCollection2.Add($IscutoverAttribute)

            $MigrationEndpoint = New-Object System.Management.Automation.RuntimeDefinedParameter('MigrationEndpoint', [String], $attributeCollection1)
            $paramDictionary.Add('MigrationEndpoint', $MigrationEndpoint)

            $IsCutover = New-Object System.Management.Automation.RuntimeDefinedParameter('IsCutover', [Nullable[boolean]], $attributeCollection2)
            $paramDictionary.Add('IsCutover', $IsCutover)
        }
        elseif ($MigrationType -eq "Mig-FileSharesToOneDrive") {
            $Office365UPNAccountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $TargetDocumentLibraryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $FileCountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($Office365UPNAccountAttribute)
            $attributeCollection2.Add($TargetDocumentLibraryAttribute)
            $attributeCollection3.Add($FileCountAttribute)

            $Office365UPNAccount = New-Object System.Management.Automation.RuntimeDefinedParameter('Office365UPNAccount', [String], $attributeCollection1)
            $paramDictionary.Add('Office365UPNAccount', $Office365UPNAccount)

            $TargetDocumentLibrary = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetDocumentLibrary', [String], $attributeCollection2)
            $paramDictionary.Add('TargetDocumentLibrary', $TargetDocumentLibrary)

            $FileCount = New-Object System.Management.Automation.RuntimeDefinedParameter('FileCount', [String], $attributeCollection3)
            $paramDictionary.Add('FileCount', $FileCount)
        }
        elseif ($MigrationType -eq "Mig-FileSharesToTeamSites") {
            $TargetSharePointSiteAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $TargetDocumentLibraryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $FileCountAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($TargetSharePointSiteAttribute)
            $attributeCollection2.Add($TargetDocumentLibraryAttribute)
            $attributeCollection3.Add($FileCountAttribute)

            $TargetSharePointSite = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetSharePointSite', [String], $attributeCollection1)
            $paramDictionary.Add('TargetSharePointSite', $TargetSharePointSite)

            $TargetDocumentLibrary = New-Object System.Management.Automation.RuntimeDefinedParameter('TargetDocumentLibrary', [String], $attributeCollection2)
            $paramDictionary.Add('TargetDocumentLibrary', $TargetDocumentLibrary)

            $FileCount = New-Object System.Management.Automation.RuntimeDefinedParameter('FileCount', [String], $attributeCollection3)
            $paramDictionary.Add('FileCount', $FileCount)
        }
        elseif ($MigrationType -eq "Mig-Domino-BAM") {
            $O365UsageLocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $O365DisplayNameAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LicenseSubscriptionIDAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $InPlaceHoldIdentityAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $HasBlackBerryAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $VIPAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $DominoBESServerAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $SecondPassEmailAddressAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection4 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection5 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection6 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection7 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection8 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($O365UsageLocationAttribute)
            $attributeCollection2.Add($O365DisplayNameAttribute)
            $attributeCollection3.Add($LicenseSubscriptionIDAttribute)
            $attributeCollection4.Add($InPlaceHoldIdentityAttribute)
            $attributeCollection5.Add($HasBlackBerryAttribute)
            $attributeCollection6.Add($VIPAttribute)
            $attributeCollection7.Add($DominoBESServerAttribute)
            $attributeCollection8.Add($SecondPassEmailAddressAttribute)

            $O365UsageLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('O365UsageLocation', [String], $attributeCollection1)
            $paramDictionary.Add('O365UsageLocation', $O365UsageLocation)

            $O365DisplayName = New-Object System.Management.Automation.RuntimeDefinedParameter('O365DisplayName', [String], $attributeCollection2)
            $paramDictionary.Add('O365DisplayName', $O365DisplayName)

            $LicenseSubscriptionID = New-Object System.Management.Automation.RuntimeDefinedParameter('LicenseSubscriptionID', [String], $attributeCollection3)
            $paramDictionary.Add('LicenseSubscriptionID', $LicenseSubscriptionID)

            $InPlaceHoldIdentity = New-Object System.Management.Automation.RuntimeDefinedParameter('InPlaceHoldIdentity', [String], $attributeCollection4)
            $paramDictionary.Add('InPlaceHoldIdentity', $InPlaceHoldIdentity)

            $HasBlackBerry = New-Object System.Management.Automation.RuntimeDefinedParameter('HasBlackBerry', [String], $attributeCollection5)
            $paramDictionary.Add('HasBlackBerry', $HasBlackBerry)

            $VIP = New-Object System.Management.Automation.RuntimeDefinedParameter('VIP', [String], $attributeCollection6)
            $paramDictionary.Add('VIP', $VIP)

            $DominoBESServer = New-Object System.Management.Automation.RuntimeDefinedParameter('DominoBESServer', [String], $attributeCollection7)
            $paramDictionary.Add('DominoBESServer', $DominoBESServer)

            $SecondPassEmailAddress = New-Object System.Management.Automation.RuntimeDefinedParameter('SecondPassEmailAddress', [String], $attributeCollection8)
            $paramDictionary.Add('SecondPassEmailAddress', $SecondPassEmailAddress)
        }
        elseif ($MigrationType -eq "Mig-Box" -or $MigrationType -eq "Mig-GoogleDrive") {
            $FilesOwnedAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($FilesOwnedAttribute)
            $FilesOwned = New-Object System.Management.Automation.RuntimeDefinedParameter('FilesOwned', [String], $attributeCollection)
            $paramDictionary.Add('FilesOwned', $FilesOwned)
        }
        elseif ($MigrationType -eq "Mig-Domino-ODME") {
            $O365UsageLocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $O365DisplayNameAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LotusNotesNameAttribute  = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $LocationAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $ResourceAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection3 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection4 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection5 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($O365UsageLocationAttribute)
            $attributeCollection2.Add($O365DisplayNameAttribute)
            $attributeCollection3.Add($LotusNotesNameAttribute )
            $attributeCollection4.Add($LocationAttribute)
            $attributeCollection5.Add($ResourceAttribute)

            $O365UsageLocation = New-Object System.Management.Automation.RuntimeDefinedParameter('O365UsageLocation', [String], $attributeCollection1)
            $paramDictionary.Add('O365UsageLocation', $O365UsageLocation)

            $O365DisplayName = New-Object System.Management.Automation.RuntimeDefinedParameter('O365DisplayName', [String], $attributeCollection2)
            $paramDictionary.Add('O365DisplayName', $O365DisplayName)

            $LotusNotesName= New-Object System.Management.Automation.RuntimeDefinedParameter('LotusNotesName', [String], $attributeCollection3)
            $paramDictionary.Add('LotusNotesName', $LotusNotesName )

            $Location = New-Object System.Management.Automation.RuntimeDefinedParameter('Location', [String], $attributeCollection4)
            $paramDictionary.Add('Location', $Location)

            $Resource = New-Object System.Management.Automation.RuntimeDefinedParameter('Resource', [String], $attributeCollection5)
            $paramDictionary.Add('Resource', $Resource)
        }
        elseif ($MigrationType -eq "Mig-IMAP") {
            $PasswordAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($PasswordAttribute)
            $Password = New-Object System.Management.Automation.RuntimeDefinedParameter('Password', [String], $attributeCollection)
            $paramDictionary.Add('Password', $Password)
        }
        elseif ($MigrationType -eq "Mig-GroupWise") {
            $PoHostingTheMailboxAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $SoapPortAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }

            $attributeCollection1 = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection2 = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection1.Add($PoHostingTheMailboxAttribute)
            $attributeCollection2.Add($SoapPortAttribute)

            $PoHostingTheMailbox = New-Object System.Management.Automation.RuntimeDefinedParameter('PoHostingTheMailbox', [String], $attributeCollection1)
            $paramDictionary.Add('PoHostingTheMailbox', $PoHostingTheMailbox)

            $SoapPort = New-Object System.Management.Automation.RuntimeDefinedParameter('SoapPort', [String], $attributeCollection2)
            $paramDictionary.Add('SoapPort', $SoapPort)
        }
        elseif ($MigrationType -eq "Mig-GoogleSites") {
            $HoldAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($HoldAttribute)
            $Hold = New-Object System.Management.Automation.RuntimeDefinedParameter('Hold', [String], $attributeCollection)
            $paramDictionary.Add('Hold', $Hold)
        }
        elseif ($MigrationType -eq "MIG-SPOnPrem") {
            $HoldAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]
            $attributeCollection.Add($HoldAttribute)
            $Hold = New-Object System.Management.Automation.RuntimeDefinedParameter('Hold', [String], $attributeCollection)
            $paramDictionary.Add('Hold', $Hold)
        }
        else { }

        if($MigrationType) {
            return $paramDictionary
        }
    }
    Process
    {
        try
        {
            if($global:MsoAdminProperties.Count -eq 0)
            {
                Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
                return
            }

            [string]$tenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

            [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

            $PropertyBag = SetPropertyBag -MigrationType $MigrationType
            $jsonObj = SetUpdateRequestValues -TenantID: $global:MsoAdminProperties["MSO-CompanyTenantInfo"] `
                                    -CompanyName: $global:MsoAdminProperties["MSO-CompanyInfo"].DisplayName `
                                    -LogonUserEmail: $global:MsoAdminProperties["MSO-LoggedOnUser"].Account `
                                    -MigrationType: $MigrationType `
                                    -Source: $Source `
                                    -Target: $Target `
                                    -MigrationDate: $MigrationDate `
                                    -MigrationWindow: $MigrationWindow `
                                    -MigrationGroup: $MigrationGroup `
                                    -Size: $Size `
                                    -IsCutover $IsCutover.Value `
                                    -Region $Region `
                                    -PropertyBag: $PropertyBag

            $serializedJson = $jsonObj | ConvertTo-Json -Compress: $true

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID",$TenantId)
            Write-Host "Sending Schedule Update Request..."

            $JsonResult = Invoke-PutRequest -Uri ([System.String]::Format("{0}Schedule/{1}",$global:CsiApiBaseUriFormat, $ScheduleUserId)) -Headers $header -Body $serializedJson

            if($JsonResult.StatusCode -ne $null)
            {
                # Error?
                Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
            }
            else
            {
                Waiting-TransactionComplete -TransactionID ($JsonResult.TransactionId)
            }
        }
        catch
        {
            Write-Warning -Message:"An error occurred attempting to authenticate with this module"
            Write-Warning -Message: $_.Exception.Message
            Write-Host "Press the [enter] key to close this process"
            Read-Host
        }
    }
}

Function Remove-FastTrackMigrationSchedule {
<#
.SYNOPSIS
    Remove an existing FastTrack schedule.
.DESCRIPTION
    The Remove-FastTracikMigrationSchedule cmdlet invokes REST API with input ScheduleId parameter. The ScheduleId is used by the API to define the migration schedules to be deleted. The DeleteType paramter is used to define the type of delete operation to be performed on the migration.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.PARAMETER ScheduleUserId
    Unique Guid for FastTrack schedule.
.PARAMETER DeleteType
    Delete type to remove specified FastTrack schedule. This can be either ForceDelete or VerifyDelete.
.EXAMPLE
    Remove-FastTrackMigrationSchedule -ScheduleUserId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -DeleteType: "ForceDelete"
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the Transaction ID .
.LINK
    Get-FastTrackMigrationSchedule
    Set-FastTrackMigrationSchedule
    New-FastTrackMigrationSchedule
    New-FastTrackMigrationScheduleFromCsv
    Get-FastTrackMigrationDeleteTypes
#>

    param(
                     [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
                     [Alias("ScheduleId")]
                     [string] $ScheduleUserId,
                     [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
                     [string] $DeleteType
              )
    try
    {
        try {
            $isError = [GUID]::Parse($ScheduleUserId)
        }
        catch {
            Write-Warning "ScheduleUserId is not a valid GUID format. To obtain the ScheduleUserId , please run Get-FastTrackMigrationSchedule to retrieve a list of all schedules."
            return
        }

        if($global:MsoAdminProperties.Count -eq 0)
        {
            Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
            return
        }

        [string] $ApiKey = $global:MsftApiKey

        [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

        $Identity = SetIdentityRecipientValues

        $CustomerObject = (New-Object PSObject |
                            Add-Member -PassThru NoteProperty Customer $Identity |
                            Add-Member -PassThru NoteProperty DeleteType $DeleteType |
                            Add-Member -PassThru NoteProperty EnvironmentType $global:MsoComOrGov )

        $serializedJson = $CustomerObject | ConvertTo-Json -Compress: $true

        $header = @{}
        if($global:v2FeatureFlag -eq $true){
        $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
        else{
        $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
        $header.Add("TENANT_ID",$TenantId)
        Write-Host "Sending Schedule Delete Request..."

        $JsonResult = Invoke-DeleteRequest -Uri ([System.String]::Format("{0}Schedule/{1}",$global:CsiApiBaseUriFormat, $ScheduleUserId)) -Headers $header -Body $serializedJson

        if($JsonResult.StatusCode -ne $null)
        {
            # Error?
            Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
        }
        else
        {
            Waiting-TransactionComplete -TransactionID ($JsonResult.TransactionId)
        }
    }
    catch
    {
        Write-Warning -Message:"An error occurred attempting to authenticate with this module"
        Write-Warning -Message: $_.Exception.Message
        Write-Host "Press the [enter] key to close this process"
        Read-Host
    }
}

Function New-FastTrackMigrationScheduleFromCsv {
<#
.SYNOPSIS
    Creates a new FastTrack schedule from CSV
.DESCRIPTION
    The New-FastTrackMigrationScheduleFromCsv command allows you to upload a full migration schedule in bulk as a CSV file. If you want to upload a single schedule, please use the New-FastTrackMigrationSchedule command.
 
    In order to use this command, you must first login using the Login-FastTrackAcount command.
.PARAMETER MigrationType
    This is the type of migration you're wanting to schedule.
 
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExCutover
        Cutover Migration
    Mig-ExStaged
        Staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GoogleSites
        GoogleSites Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    MIG-SPOnPrem
        Sharepoint Migration
.PARAMETER IsCutover
    Is cutover $true | $false | $null.
.PARAMETER Region
    Name of region.
.PARAMETER FilePath
    Specifies the path to the Schedule CSV file .
.EXAMPLE
    New-FastTrackMigrationScheduleFromCsv -MigrationType "Mig-Box" -Region "US" -FilePath "C:\filename.csv"
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the Transaction ID .
.LINK
    New-FastTrackMigrationSchedule
    Get-FastTrackMigrationSchedule
    Set-FastTrackMigrationSchedule
    Remove-FastTrackMigrationSchedule
    Get-FastTrackMigrationDeleteTypes
#>

    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [ValidateSet("Mig-ExHybrid","Mig-ExSimpleMRS","Mig-ExCutover","Mig-ExStaged","Mig-IMAP","Mig-GmailCutover","Mig-GmailStaged","Mig-GroupWise","Mig-GoogleDrive","Mig-GoogleSites","Mig-Box","Mig-FileSharesToOneDrive","Mig-FileSharesToTeamSites","Mig-Domino-BAM","Mig-Domino-ODME","MIG-SPOnPrem")]
        [string] $MigrationType,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string] $Region,
        [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
        [ValidateSet($true, $false, $null)]
        [Nullable[boolean]] $IsCutover,
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string] $FilePath
        )
    try
    {
        if($global:MsoAdminProperties.Count -eq 0)
        {
            Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
            return
        }

        $FileContentStr = Get-CsvAsJson -FilePath $FilePath

        if($FileContentStr -ne "[]")
        {
            [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]
            [string] $CompanyName = $global:MsoAdminProperties["MSO-CompanyInfo"].DisplayName
            [string] $LogOnUserEmail = $global:MsoAdminProperties["MSO-LoggedOnUser"].Account
            [string] $ApiKey = $global:MsftApiKey

            $CustomerIdentity = (New-Object PSObject |
                Add-Member -PassThru NoteProperty TenantId $TenantId |
                Add-Member -PassThru NoteProperty CompanyName $CompanyName |
                Add-Member -PassThru NoteProperty LogOnUserEmail $LogOnUserEmail)

            $FormattedJson = New-Object psobject |
                Add-Member -PassThru NoteProperty Customer $CustomerIdentity |
                Add-Member -PassThru NoteProperty ScheduleType $MigrationType |
                Add-Member -PassThru NoteProperty Schedules $FileContentStr |
                Add-Member -PassThru NoteProperty Region $Region |
                Add-Member -PassThru NoteProperty IsCutover $IsCutover |
                Add-Member -PassThru NoteProperty EnvironmentType $global:MsoComOrGov

            $Output = $FormattedJson | ConvertTo-Json -Compress: $true

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID", $TenantId)
            Write-Host "Sending New Schedule From CSV Request..."

            $result = Invoke-PostRequest -Uri ([System.String]::Format("{0}Schedule/Create/Batch", $global:CsiApiBaseUriFormat)) -Headers $header -Body $Output

            if($result.StatusCode -ne $null)
            {
                Write-Warning "Request failed! : $($result.StatusCode) - Error Message: $($result)"
            }
            else
            {
                Waiting-TransactionComplete -TransactionID ($result.TransactionId)
            }
        }
        else
        {
            Write-Warning "File ($($FilePath)) is not in valid CSV format."
        }
    }
    catch
    {
        Write-Warning -Message:"An error occurred attempting to authenticate with this module"
        Write-Warning -Message: $_.Exception.Message
        Write-Host "Press the [enter] key to close this process"
        Read-Host
    }
}

Function Get-FastTrackMigrationScheduleTemplate {
    <#
    .SYNOPSIS
        Get sample template of CSV file which upload in FastTrack schedule.
    .DESCRIPTION
        The Get-FastTrackMigrationScheduleTemplate cmdlet invokes the REST API to retrieve the correct CSV file template, based on the input FastTrack migration type. The retrieved template is saved to the directory declared by the Path parameter.
 
        In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
    .PARAMETER MigrationType
    This is the type of migration you're wanting to schedule.
 
    Mig-ExHybrid
        Exchange to Exchange hybrid migration
    Mig-ExSimpleMRS
        Exchange to Exchange hybrid migration
    Mig-ExCutover
        Cutover Migration
    Mig-ExStaged
        Staged Migration
    Mig-IMAP
        IMAP Migration
    Mig-GmailCutover
        Gmail Cutover Migration
    Mig-GmailStaged
        Gmail staged Migration
    Mig-GroupWise
        GroupWise Migration
    Mig-GoogleDrive
        Google drive to OneDrive migration
    Mig-GoogleSites
        GoogleSites Migration
    Mig-Box
        Box drive to OneDrive migration
    Mig-FileSharesToOneDrive
        FileShare to OneDrive migration
    Mig-FileSharesToTeamSites
        FileShare to TeamSite migration
    Mig-Domino-BAM
        Notes user documents into BAM (Binary Tree Application Manager) migration
    Mig-Domino-ODME
        Notes user documents into ODME migration
    MIG-SPOnPrem
        Sharepoint Migration
    .PARAMETER Path
        Output path of template file.
    .EXAMPLE
        Get-FastTrackMigrationScheduleTemplate -MigrationType "Mig-Box" -Folderpath 'C:/template'
    .INPUTS
        System.String
    .OUTPUTS
        System.IO
            This cmdlet generates a File object.
    .LINK
        New-FastTrackMigrationScheduleFromCsv
    #>

    [cmdletbinding()]
     param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [ValidateSet("Mig-ExHybrid","Mig-ExSimpleMRS","Mig-ExCutover","Mig-ExStaged","Mig-IMAP","Mig-GmailCutover","Mig-GmailStaged","Mig-GroupWise","Mig-GoogleDrive","Mig-GoogleSites","Mig-Box","Mig-FileSharesToOneDrive","Mig-FileSharesToTeamSites","Mig-Domino-BAM","Mig-Domino-ODME","MIG-SPOnPrem")]
        [string] $MigrationType = $(throw "This migration type is not valid."),
        [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
        [string] $FolderPath = $null
    )

    DynamicParam
    {
        if($MigrationType -eq "Mig-ExHybrid" -or $MigrationType -eq "Mig-ExSimpleMRS" -or $MigrationType -eq "Mig-ExCutover" -or $MigrationType -eq "Mig-ExStaged") {
            $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

            $IscutoverAttribute = New-Object System.Management.Automation.ParameterAttribute -Property @{ Mandatory = $false }
            $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]

            $attributeCollection.Add($IscutoverAttribute)

            $IsCutover = New-Object System.Management.Automation.RuntimeDefinedParameter('IsCutover', [Nullable[boolean]], $attributeCollection)
            $paramDictionary.Add('IsCutover', $IsCutover)

            return $paramDictionary
        }
    }
    Process
    {
        try
        {
            if($global:MsoAdminProperties.Count -eq 0)
            {
                Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
                return
            }

            if($FolderPath)
            {
                if((Test-Path -Path $FolderPath -ErrorAction: SilentlyContinue) -ne $true )
                {
                    Write-Warning "Unable to find path you entered - $FolderPath"
                    return
                }
                $filename = $MigrationType + '_' + ('{0:yyyyMMdd_HHmmss}' -f (Get-Date))
                $newFilefullPath = $FolderPath + "\" + $filename + ".csv"
            }

            Write-Host "Retrieving template - " -NoNewline; Write-Host $MigrationType -ForegroundColor Yellow;

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID", $global:MsoAdminProperties["MSO-CompanyTenantInfo"])

            if($IsCutover.Value -eq "false")
            {
                $IsCutoverOb = "false"
            }
            elseif($IsCutover.Value -eq "true")
            {
                $IsCutoverOb = "true"
            }
            else
            {
                $IsCutoverOb = $null
            }

            $JsonResult = Invoke-GetRequest -Uri ([System.String]::Format("{0}Schedule/Template?MigrationType={1}&IsCutover={2}&environmentType={3}", $global:CsiApiBaseUriFormat, $MigrationType, $IsCutover.Value, $global:MsoComOrGov)) -Headers $header

            if($JsonResult.StatusCode -ne $null)
            {
                Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
                return
            }
            else
            {
                if(!$FolderPath)
                {
                    Write-Host "`n"
                    [Regex]::Split($JsonResult.data,"\\r\\n")
                    return
                }

                $tempData = ([Regex]::Split($JsonResult.data,"\\r\\n")) | ConvertFrom-Csv
                $tempData | Export-Csv -NoTypeInformation -Path $newFilefullPath

                Write-Host "`nCSV Template file successfully generated."
                Write-Host "File location : " -NoNewline; Write-Host $newFilefullPath -ForegroundColor Yellow

                Write-Host "`nDo you want to open ?"
                $input = Read-Host '[F] File [P] Folder Path [S] Suspend (default is "F")'

                switch(([string]$input).ToUpper())
                {
                    "S" {  }
                    "P" { ii $FolderPath }
                    default { Invoke-Item $newFilefullPath }
                }

            }
        }
        catch
        {
            Write-Warning -Message:"An error occurred attempting to authenticate with this module"
            Write-Warning -Message: $_.Exception.Message
            Write-Host "Press the [enter] key to close this process"
            Read-Host
        }
    }
}

Function Get-FastTrackMigrationDeleteTypes {
<#
.SYNOPSIS
    Get FastTrack delete types.
.DESCRIPTION
    The Get-FastTrackMigrationDeleteTypes cmdlet utilizes the REST API call to retrieve a list of available delete types used to schedule deletion of FastTrack schedule.
 
    In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
.EXAMPLE
    Get-FastTrackMigrationDeleteTypes
.INPUTS
    System.String
.OUTPUTS
    System.Management.Automation.PSObject
        This cmdlet generates a System.Management.Automation.PSObject object that represents the list of possible delete types for FastTrack schedule delete.
.LINK
    New-FastTrackMigrationSchedule
    Set-FastTrackMigrationSchedule
    Remove-FastTrackMigrationSchedule
    New-FastTrackMigrationScheduleFromCsv
    Get-FastTrackMigrationSchedule
#>

        try
        {
            if($global:MsoAdminProperties.Count -eq 0)
            {
                Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
                return
            }

            [string] $ApiKey = $global:MsftApiKey
            [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID",$TenantId)
            Write-Host "Sending Schedule Get Request..."

            $query += "environmentType=$global:MsoComOrGov"
            $JsonResult = Invoke-GetRequest -Uri ([System.String]::Format("{0}Schedule/DeleteTypes?$($query)", $global:CsiApiBaseUriFormat)) -Headers $header

            if($JsonResult.StatusCode -ne $null)
            {
                Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
            }
            else
            {
                Write-Host "Get request completed"
            }

            return $JsonResult
        }
        catch
        {
            Write-Warning -Message:"An error occurred attempting to authenticate with this module"
            Write-Warning -Message: $_.Exception.Message
            Write-Host "Press the [enter] key to close this process"
            Read-Host
        }
}

Function Get-FastTrackMigrationTypes {
    <#
    .SYNOPSIS
        Get FastTrack Migration Types.
    .DESCRIPTION
        This cmdlet is used to get all the migration types to execute FastTrack schedules.
 
        In order to use this cmdlet, you must first login using the Login-FastTrackAcount cmdlet.
    .EXAMPLE
        FastTrackMigrationTypes
    .INPUTS
        System.String
    .OUTPUTS
        System.Management.Automation.PSObject
            This cmdlet generates a System.Management.Automation.PSObject object that represents the list of possible migration types for FastTrack schedule operation.
    .LINK
        New-FastTrackMigrationSchedule
        Set-FastTrackMigrationSchedule
        New-FastTrackMIgrationScheduleFromCsv
    #>

        try
        {
            if($global:MsoAdminProperties.Count -eq 0)
            {
                Write-Warning "Unable to retrieve Office 365 credentials! :: Please call [Login-FastTrackAccount] function."
                return
            }

            [string] $ApiKey = $global:MsftApiKey
            [string] $TenantId = $global:MsoAdminProperties["MSO-CompanyTenantInfo"]

            $header = @{}
            if($global:v2FeatureFlag -eq $true){
            $header.Add("Authorization", $global:MsoAdminProperties["AuthorizationResult"].CreateAuthorizationHeader())}
            else{
            $header.Add("ACCESS_TOKEN",$global:MsftAccessToken)}
            $header.Add("TENANT_ID",$TenantId)
            Write-Host "Sending Migration type Get Request..."

            $query += "environmentType=$global:MsoComOrGov"
            $JsonResult = Invoke-GetRequest -Uri ([System.String]::Format("{0}Schedule/MigrationTypes?$($query)", $global:CsiApiBaseUriFormat)) -Headers $header

            if($JsonResult.StatusCode -ne $null)
            {
                Write-Warning "Request failed! : $($JsonResult.StatusCode) - Error Message: $($JsonResult)"
            }
            else
            {
                Write-Host "Get request completed"
                return $JsonResult.MigrationTypes
            }

            return $JsonResult
        }
        catch
        {
            Write-Warning -Message:"An error occurred attempting to authenticate with this module"
            Write-Warning -Message: $_.Exception.Message
            Write-Host "Press the [enter] key to close this process"
            Read-Host
        }
}

Function Clear-FastTrackMigrationSchedules {
    <#
        .SYNOPSIS
            Allow for the deletion of multiple schedules
        .DESCRIPTION
            This PowerShell is to allow a user to select and delete multiple schedules for a customer
    #>


    $scheduleUserId = ( Get-FastTrackMigrationSchedule | Out-GridView -Title "Select schedules to remove (cancel to abort)" -PassThru).ScheduleUserId
    foreach ($scheduleUser in $scheduleUserId) {Remove-FastTrackMigrationSchedule -ScheduleId $scheduleUser -DeleteType: "ForceDelete" }
}

Function Update-FastTrackMigrationSchedules {
    <#
        .SYNOPSIS
            Allow for the update of multiple schedules
        .DESCRIPTION
            This PowerShell function is to allow a user to select and update multiple schedules for a customer.
            Only Migration Window, Migration Group and Migration Date can be updated.
        .PARAMETER MigrationDate
            Date of migration.
        .PARAMETER MigrationWindow
            Migration event window.
        .PARAMETER MigrationGroup
            Migration group.
    #>


    param(
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationDate,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationWindow,
            [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [string] $MigrationGroup
        )

    # Get the schedules associated to the customer and pipe them into a grid.
    $selectedSchedules = ( Get-FastTrackMigrationSchedule | Out-GridView -Title "Select a set of schedules to update" -PassThru)

    foreach ($selectedSchedule in $selectedSchedules)
    {
            # Besides updating the base/required schedule parameters certain migration types also have extra paramerters that must also be passed in to the Set-FastTrackMigrationSchedule cmdlet
            if ($selectedSchedule.MigrationType -eq "Mig-ExHybrid" -or $selectedSchedule.MigrationType -eq "Mig-ExSimpleMRS" -or $selectedSchedule.MigrationType -eq "Mig-ExCutover" -or $selectedSchedule.MigrationType -eq "Mig-ExStaged") {
                # Update base schedule parameters + MigrationEndpoint and IsCutover parameters
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -MigrationEndpoint $selectedSchedule.MigrationEndpoint -IsCutover $selectedSchedule.IsCutover
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-FileSharesToOneDrive") {
                # Update base schedule parameters + Office365UPNAccount, TargetDocumentLibrary and FileCount parameters
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -Office365UPNAccount $selectedSchedule.Office365UPNAccount -TargetDocumentLibrary $selectedSchedule.TargetDocumentLibrary -FileCount $selectedSchedule.FileCount
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-FileSharesToTeamSites") {
                # Update base schedule parameters + TargetSharePointSite, TargetDocumentLibrary and FileCount parameters
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -TargetSharePointSite $selectedSchedule.TargetSharePointSite -TargetDocumentLibrary $selectedSchedule.TargetDocumentLibrary -FileCount $selectedSchedule.FileCount
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-Domino-BAM") {
                # Update base schedule parameters + O365UsageLocation, O365DisplayName, LicenseSubscriptionID, InPlaceHoldIdentity, HasBlackBerry, VIP, DominoBESServer and SecondPassEmailAddress parameters
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -O365UsageLocation $selectedSchedule.O365UsageLocation -O365DisplayName $selectedSchedule.O365DisplayName -LicenseSubscriptionID $selectedSchedule.LicenseSubscriptionID -InPlaceHoldIdentity $selectedSchedule.InPlaceHoldIdentity -HasBlackBerry $selectedSchedule.HasBlackBerry -VIP $selectedSchedule.VIP -DominoBESServer $selectedSchedule.DominoBESServer -SecondPassEmailAddress $selectedSchedule.SecondPassEmailAddress
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-Box" -or $selectedSchedule.MigrationType -eq "Mig-GoogleDrive") {
                # Update base schedule parameters + FilesOwned paramerter
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -FilesOwned $selectedSchedule.FilesOwned
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-Domino-ODME") {
                # Update base schedule parameters + Lotus Notes Name,Location (Site Name),Resource (Room/Equipment),Internet Address,O365 UPN,O365 Display Name and O365 Usage Location parameters
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -O365UsageLocation $selectedSchedule.O365UsageLocation -O365DisplayName $selectedSchedule.O365DisplayName -LotusNotesName $selectedSchedule.LotusNotesName -Location $selectedSchedule.Location -Resource $selectedSchedule.Resource 
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-IMAP" ) {
                # Update base schedule parameters + FilesOwned paramerter
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -Hold $selectedSchedule.Password
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-GroupWise" ) {
                # Update base schedule parameters + FilesOwned paramerter
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -PoHostingTheMailbox $selectedSchedule.PoHostingTheMailbox -SoapPort $selectedSchedule.SoapPort
            }
            elseif ($selectedSchedule.MigrationType -eq "Mig-GoogleSites" ) {
                # Update base schedule parameters + FilesOwned paramerter
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -Hold $selectedSchedule.Hold
            }
            elseif ($selectedSchedule.MigrationType -eq "MIG-SPOnPrem" ) {
                # Update base schedule parameters + FilesOwned paramerter
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region -Hold $selectedSchedule.Hold
            }
            else {
                # Update base schedule parameters only
                Set-FastTrackMigrationSchedule -ScheduleId $selectedSchedule.ScheduleUserId -MigrationType $selectedSchedule.MigrationType -Source $selectedSchedule.Source -Target $selectedSchedule.Target -MigrationDate $MigrationDate -MigrationWindow $MigrationWindow -MigrationGroup $MigrationGroup -Size $selectedSchedule.Size -Region $selectedSchedule.Region
            }
    }
}
# SIG # Begin signature block
# MIIkWwYJKoZIhvcNAQcCoIIkTDCCJEgCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBT3nWIDVWmApMh
# hEcOcm9Ns25P3ClaPGHUhSFZ318KLaCCDYEwggX/MIID56ADAgECAhMzAAABA14l
# HJkfox64AAAAAAEDMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMTgwNzEyMjAwODQ4WhcNMTkwNzI2MjAwODQ4WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDRlHY25oarNv5p+UZ8i4hQy5Bwf7BVqSQdfjnnBZ8PrHuXss5zCvvUmyRcFrU5
# 3Rt+M2wR/Dsm85iqXVNrqsPsE7jS789Xf8xly69NLjKxVitONAeJ/mkhvT5E+94S
# nYW/fHaGfXKxdpth5opkTEbOttU6jHeTd2chnLZaBl5HhvU80QnKDT3NsumhUHjR
# hIjiATwi/K+WCMxdmcDt66VamJL1yEBOanOv3uN0etNfRpe84mcod5mswQ4xFo8A
# DwH+S15UD8rEZT8K46NG2/YsAzoZvmgFFpzmfzS/p4eNZTkmyWPU78XdvSX+/Sj0
# NIZ5rCrVXzCRO+QUauuxygQjAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUR77Ay+GmP/1l1jjyA123r3f3QP8w
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDM3OTY1MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAn/XJ
# Uw0/DSbsokTYDdGfY5YGSz8eXMUzo6TDbK8fwAG662XsnjMQD6esW9S9kGEX5zHn
# wya0rPUn00iThoj+EjWRZCLRay07qCwVlCnSN5bmNf8MzsgGFhaeJLHiOfluDnjY
# DBu2KWAndjQkm925l3XLATutghIWIoCJFYS7mFAgsBcmhkmvzn1FFUM0ls+BXBgs
# 1JPyZ6vic8g9o838Mh5gHOmwGzD7LLsHLpaEk0UoVFzNlv2g24HYtjDKQ7HzSMCy
# RhxdXnYqWJ/U7vL0+khMtWGLsIxB6aq4nZD0/2pCD7k+6Q7slPyNgLt44yOneFuy
# bR/5WcF9ttE5yXnggxxgCto9sNHtNr9FB+kbNm7lPTsFA6fUpyUSj+Z2oxOzRVpD
# MYLa2ISuubAfdfX2HX1RETcn6LU1hHH3V6qu+olxyZjSnlpkdr6Mw30VapHxFPTy
# 2TUxuNty+rR1yIibar+YRcdmstf/zpKQdeTr5obSyBvbJ8BblW9Jb1hdaSreU0v4
# 6Mp79mwV+QMZDxGFqk+av6pX3WDG9XEg9FGomsrp0es0Rz11+iLsVT9qGTlrEOla
# P470I3gwsvKmOMs1jaqYWSRAuDpnpAdfoP7YO0kT+wzh7Qttg1DO8H8+4NkI6Iwh
# SkHC3uuOW+4Dwx1ubuZUNWZncnwa6lL2IsRyP64wggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIWMDCCFiwCAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAQNeJRyZH6MeuAAAAAABAzAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgT9nRr7CQ
# S4RRcCftKdxVrmxDJZI/qn0iP4fXksiqMeYwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQAaUbNNUBXyboMjcViLJ4j4/uYizh2rfOrChXO/ZoPz
# DoqScYmToUByu418N1m9btzxlZx46sv6chjpaOqdgtMQC0AuDeK6g/nfGD8eYt6R
# 3jZG+Ob5qQM+MHIgwLbt318tLw9wxbzY0H0HGHETRuvjxqtK+8bqumemT0I0ioKB
# jSpxjfreGDUCfBduGm6oQhCfv91TpyAmffroUYqkH4OYoUgAgU21TzJkweRXNSJb
# pN0NN3BCYFI/XgmcPEZd+/1OccYnT/5fYEX/qqr6ItLlGoVtE8uHrM0NK3Q/a0Ee
# kErj00jibOseLkSdBwQc7BsmSbsixsYgEIhu7JH//Vp7oYITujCCE7YGCisGAQQB
# gjcDAwExghOmMIITogYJKoZIhvcNAQcCoIITkzCCE48CAQMxDzANBglghkgBZQME
# AgEFADCCAVgGCyqGSIb3DQEJEAEEoIIBRwSCAUMwggE/AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIAWOQEdtTvnOJk57BBZOEJqH2GwtA+1hAv9kpCVU
# ExZdAgZcShKP8UQYEzIwMTkwMjA2MTgzMDU4LjE0M1owBwIBAYACAfSggdSkgdEw
# gc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsT
# IE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFs
# ZXMgVFNTIEVTTjo3MjhELUM0NUYtRjlFQjElMCMGA1UEAxMcTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgU2VydmljZaCCDyIwggT1MIID3aADAgECAhMzAAAA09CUVp0OvYMG
# AAAAAADTMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy
# MDEwMB4XDTE4MDgyMzIwMjY0MFoXDTE5MTEyMzIwMjY0MFowgc4xCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo3
# MjhELUM0NUYtRjlFQjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7ynC6AF22joS/v
# TPZsIG82oovZ8kXNQcF6/17dZtRllU6pCGV8zMxSQOXTWD2MZRJ/OqfHUSYCNTPa
# knetNsrZhstlFNT09QBjjeVXayDG/aI8JPy91P5riOAFk/gvjnQCdcoV65OBF286
# bs2lgUa6rc2qKHwDVpR1w+2jXrS8Jtz6omUgfB7CMpw1ZwMeQ/+Fb43EAIxeNXB5
# uq/ZYPDA+iMitkdhrjQJgPKKQqhPiYcz3KdrAk34V6y/zUw8FuJ9Zi89actfoS0e
# AdSdWYDATi6oIiPAioWYQuwx6ZY+e5U8HcjGiA1bg9pnufqcnVLzInBxr8DVp1im
# mAhtkfUCAwEAAaOCARswggEXMB0GA1UdDgQWBBQoUcoPr2oQO5sHaVpYVKDsatRn
# eDAfBgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEug
# SaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9N
# aWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsG
# AQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Rp
# bVN0YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQA9YvD9FBa0sIj/Q8252GXwW0qQ
# aEm/oZXTh4eI6htIKASVxX8y1g4IVeD6O8YyXdBlzQUgr76B70pDgqyynwmJK6KB
# pg2bf6KOeHImc4pmofFc9EhYLZgXPXwqHJY1Rgwt4X1kCNNK6PTGeFlJproYry38
# a8AuUm0oLJpf46TLC4wQv89vfyEhBed/Wv95Ro5fqn/tAQc8S/c0eq1CAdkMDzsJ
# q7lZmiEAMaVF0vKrcRvtVu7T5BZcTmP6bHNtzcDxnn7rB6TUgSREnWP5Di46Z9P6
# 0XraNff0Ttit5Msy8ivsrcEa2CIxUgscbYDxAaWR8Ghb/rTVIEEWYBAVrF9vMIIG
# cTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1
# WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC
# ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9p
# lGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEw
# WbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeG
# MoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJ
# UGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw
# 2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0C
# AwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ
# 80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8E
# BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2U
# kFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5j
# b20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmww
# WgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29m
# dC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYD
# VR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYI
# KwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0
# AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9
# naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtR
# gkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzy
# mXlKkVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCf
# Mkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3D
# nKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs
# 9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110
# mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL
# 2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffI
# rE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxE
# PJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc
# 1bN+NR4Iuto229Nfj950iEkSoYIDsDCCApgCAQEwgf6hgdSkgdEwgc4xCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29m
# dCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVT
# Tjo3MjhELUM0NUYtRjlFQjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# U2VydmljZaIlCgEBMAkGBSsOAwIaBQADFQBnQlpxrvQi2lklNcOL1G5qmRJdZ6CB
# 3jCB26SB2DCB1TELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEp
# MCcGA1UECxMgTWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJzAlBgNV
# BAsTHm5DaXBoZXIgTlRTIEVTTjo0REU5LTBDNUUtM0UwOTErMCkGA1UEAxMiTWlj
# cm9zb2Z0IFRpbWUgU291cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0BAQUFAAIF
# AOAE55YwIhgPMjAxOTAyMDYxMjU2NTRaGA8yMDE5MDIwNzEyNTY1NFowdzA9Bgor
# BgEEAYRZCgQBMS8wLTAKAgUA4ATnlgIBADAKAgEAAgICjwIB/zAHAgEAAgIZdDAK
# AgUA4AY5FgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMBoAowCAIB
# AAIDFuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQBqk96DFl4vA/8o
# oq9hNatps/sYX2ePe2gsoFkTa5IfnPXc1Yu4TzvfId+d//MqoZuRRPJdWGbyNTRm
# T0zIlZQHAWIsa4dF8+6/fxWONYvhtzzIfXkp6ftMmDbo/xKoqpaRbC150PPpvk+R
# RFcjbpkEj0Yx1hfM+GR1mGlYEUpx4gmzlQsz2Jf38h1DZVyc9GJHxtXg5m76WDpT
# pl56H/xLUlgoSEQiJS/RG1hFD7kryW9XzMQa1lHkGmx1m9HapzN/Pm8ZIzz/jWix
# 9aPbPKeOSvKMrwnR2U63Vq8Quz7SvNAergVFJ4Rf4AgII8gSA7BxprDB6QKKK2e+
# g7Ip3N/oMYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTACEzMAAADT0JRWnQ69gwYAAAAAANMwDQYJYIZIAWUDBAIBBQCgggEyMBoGCSqG
# SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgdJMRswrC6Owb
# Sy+CUJADCWcyymrfg1wbiQuJi3xTejEwgeIGCyqGSIb3DQEJEAIMMYHSMIHPMIHM
# MIGxBBRnQlpxrvQi2lklNcOL1G5qmRJdZzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFBDQSAyMDEwAhMzAAAA09CUVp0OvYMGAAAAAADTMBYEFIPhy7ept8yk
# kI5fPc3VKcb8IW5qMA0GCSqGSIb3DQEBCwUABIIBAKz2/L3hzzEZ9Qz9sr5EwN/o
# d98ChTI3Sq60BWiiuhh6MR1Bv2YtwbKsQb1Gg/fmr1R5JpNR11xoe2YaydmieeAx
# xG2eR3QnvWGMyz0muEk0ZcU1zBWcvvyRvhQidZuD3TbnWR6oguxKzpwt7HFG119t
# p/Ggl2/kZ9vaINVHfHUGm9ZT/nl3NvxUZ47ncOsHsG0kt6lrd4tHGvA6GLUmZfdw
# 72WCjU/wKplRfz4eggYwNpy8aekk0OzkEIsWhl+pgK1HavzI6/gPEhPpfue47Mmm
# WZCpiG5QOCLbbfF8dWsWYM6y0cuXTCQZ9th6SCxpNRBNSnRh97A7CqS4tuPIDII=
# SIG # End signature block