Classes/Public/TMEvent.ps1

#region Classes

class TMEvent {

    #region Non-Static Properties

    [Nullable[Int32]]$Id
    [TMReference]$Project
    [String]$Name
    [String]$Description
    [Nullable[TMRunbookStatus]]$RunbookStatus
    [Int32]$RunbookVersion
    [String]$RunbookBridge1
    [String]$RunbookBridge2
    [String]$Videolink
    [Boolean]$ApiActionBypass = $false
    [Nullable[DateTime]]$ActualCompletionTime
    [Nullable[DateTime]]$EstStartTime
    [Nullable[DateTime]]$EstCompletionTime
    [Nullable[DateTime]]$DateCreated
    [Nullable[DateTime]]$LastUpdated
    [TMReference[]]$Tags
    [TMReference[]]$Bundles

    #endregion Non-Static Properties

    #region Constructors

    TMEvent() {}

    TMEvent([String]$name, [String]$description) {
        $this.Name = $name
        $this.Description = $description
    }

    TMEvent([String]$name, [String]$description, [Object[]]$tags) {
        $this.Name = $name
        $this.Description = $description
        if ($tags -is [TMReference[]]) {
            $this.Tags = $tags
        } else {
            $this.Tags = $tags | ForEach-Object { [TMReference]::new($_) }
        }
    }

    TMEvent([String]$name, [String]$description, [Object[]]$tags, [Object[]]$bundles) {
        $this.Name = $name
        $this.Description = $description
        if ($tags) {
            $this.Tags = $tags | ForEach-Object { [TMReference]::new($_) }
        }


        if ($bundles) {
            $this.Bundles = $bundles | ForEach-Object { [TMReference]::new($_) }
        }
    }

    TMEvent([Object]$object) {
        $this.Id = $object.id
        $this.Project = [TMReference]::new($object.project)
        $this.Name = $object.name
        $this.Description = $object.description
        try {
            $this.RunbookStatus = $object.runbookStatus ?? $object.Status
        } catch { Write-Verbose "PSScriptAnalyzer doesn't like empty catch blocks." }
        $this.RunbookVersion = $object.runbookVersion
        $this.RunbookBridge1 = $object.runbookBridge1
        $this.RunbookBridge2 = $object.runbookBridge2
        $this.Videolink = $object.videolink
        $this.ApiActionBypass = $object.apiActionBypass ?? $object.BypassActions

        # Casting from an empty string to DateTime raises an exception
        if ( -not [string]::IsNullOrEmpty($object.estStartTime) ) {
            $this.EstStartTime = $object.estStartTime
        } elseif ( -not [string]::IsNullOrEmpty($object.StartTime) ) {
            $this.EstStartTime = $object.StartTime
        }

        if ( -not [string]::IsNullOrEmpty($object.estCompletionTime) ) {
            $this.EstCompletionTime = $object.estCompletionTime
        } elseif ( -not [string]::IsNullOrEmpty($object.CompletionTime) ) {
            $this.EstCompletionTime = $object.CompletionTime
        }

        $this.DateCreated = [string]::IsNullOrEmpty($object.dateCreated) ? $null : $object.dateCreated
        $this.LastUpdated = [string]::IsNullOrEmpty($object.lastUpdated) ? $null : $object.lastUpdated

        $this.ActualCompletionTime = [string]::IsNullOrEmpty($object.actualCompletionTime) ? $null : $object.actualCompletionTime


        # Different versions of TM return different properties for Tags
        $this.Tags = $object.tags ?? $object.addTags | ForEach-Object { [TMReference]::new($_) }

        # Different versions of TM return different properties for Bundles
        $this.Bundles = foreach ($bundle in $object.bundles ?? $object.moveBundle ?? $object.moveBundlesString) {
            [TMReference]::new($bundle)
        }
    }

    #endregion Constructors

    #region Non-Static Methods

    <#
        Summary:
            Formats properties in the class instance into a JSON string that can be used with web requests to TM
        Params:
            ProjectId - An optional Project ID to be used when making calls to the REST API
        Outputs:
            A JSON string to be used as the body of a web request
    #>

    [String]GetWebRequestBody([Nullable[Int32]]$ProjectId) {
        $EventTags = @()
        if ($this.Tags) {
            $this.Tags | ForEach-Object { $EventTags += $_.Name }
        }


        $EventBundles = @(foreach ($bundle in $this.Bundles) { $bundle.Id })

        $Body = @{
            addTags           = $EventTags
            apiActionBypass   = $this.ApiActionBypass
            description       = $this.Description ?? ""
            estCompletionTime = $null -ne $this.EstCompletionTime ? (Get-Date -Date $this.EstCompletionTime -Format 'o') : ""
            estStartTime      = $null -ne $this.EstStartTime ? (Get-Date -Date $this.EstStartTime -Format 'o') : ""
            moveBundle        = $EventBundles
            name              = $this.Name
            runbookBridge1    = $this.RunbookBridge1 ?? ""
            runbookBridge2    = $this.RunbookBridge2 ?? ""
            runbookStatus     = $null -ne $this.RunbookStatus ? $this.RunbookStatus.ToString() : ""
            videolink         = $this.Videolink ?? ""
        }
        if ($ProjectId) { $Body.project = $ProjectId }

        return ($Body | ConvertTo-Json -Compress)
    }

    <#
        Summary:
            Resolves the Tags and Bundles in the class instance to have valid Names and IDs
        Params:
            TMSessionName - The name of the TMSession to use when resolving references
        Outputs:
            None
    #>

    [void]ResolveEventGroups([String]$TMSessionName) {
        $OriginalBundles = $this.Bundles
        try {
            $this.Bundles = [TMReference]::Resolve($OriginalBundles, [TMReferenceType]::Bundle, $TMSessionName)
        } catch {
            Write-Warning "Could not resolve references: $($_.Exception.Message)"
            Write-Warning "Bundles were not modified"
            $this.Bundles = $OriginalBundles
        }

        $OriginalTags = $this.Tags
        try {
            $this.Tags = [TMReference]::Resolve($OriginalTags, [TMReferenceType]::Tag, $TMSessionName)
        } catch {
            Write-Warning "Could not resolve references: $($_.Exception.Message)"
            Write-Warning "Tags were not modified"
            $this.Tags = $OriginalTags
        }
    }

    [void]ResolveEventGroups() {
        $this.ResolveEventGroups('Default')
    }

    #endregion Non-Static Methods

}

#endregion Classes

#region Enumerations

enum TMRunbookStatus {
    Pending
    Draft
    Final
    Done
}

#endregion Enumerations