lib/AssetOptions.ps1

## TM Dependency Type
function Get-TMDependencyType {
    param(
        [Parameter(Mandatory = $false)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $false)]
        [String]$Server = $global:TMSessions[$TMSession].TMServer,

        [Parameter(Mandatory = $false)]
        $AllowInsecureSSL = $global:TMSessions[$TMSession].AllowInsecureSSL,

        [Parameter(Mandatory = $false,
            Position = 1,
            ParameterSetName = 'ByType')]
        [String]$Name,

        [Parameter(Mandatory = $false)]
        [Switch]$ResetIDs
    )

    Get-TMAssetOption -TMSession $TMSession -Type 'Dependency Type' -Name $Name -ResetIDs:$ResetIDs
}


function New-TMDependencyType {
    param(
        [Parameter(Mandatory = $false)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $false)]
        [String]$Server = $global:TMSessions[$TMSession].TMServer,

        [Parameter(Mandatory = $false)]
        $AllowInsecureSSL = $global:TMSessions[$TMSession].AllowInsecureSSL,

        [Parameter(Mandatory = $true)]
        [TMDependencyType]$DependencyType
    )

    New-TMAssetOption -TMSession $TMSession -InputObject $DependencyType -Type 'Dependency Type'
}


function Get-TMAssetOption {
    <#
    .SYNOPSIS
    Retrieves one or more Asset Options from a TransitionManager instance
 
    .DESCRIPTION
    This function will retrieve one or more Asset Options (Asset Environment, Asset Plan Status,
    Asset Priority, Dependency Type, Dependency Status, Asset Type, Task Category) from
    the specified TransitionManager instance
 
    .PARAMETER TMSession
    The name of the TM Session to use when retrieving the Asset Option
 
    .PARAMETER Server
    The URI of the TransitionManager instance
 
    .PARAMETER AllowInsecureSSL
    Switch indicating that insecure SSL may be used
 
    .PARAMETER Type
    The type of TransitionManager Asset Option to retrieve
 
    .PARAMETER Name
    The Name/Label of the Asset Option
 
    .PARAMETER ResetIDs
    Switch indicating that the Asset Option(s) should be returned with IDs set to null
 
    .EXAMPLE
    Get-TMAssetOption -TMSession 'tmddev' -Type 'Task Category' -Name 'general'
 
    .EXAMPLE
    Get-TMAssetOption
 
    .EXAMPLE
    Get-TMAssetOption -Type 'Dependency Type'
 
    .OUTPUTS
    One or more TMAssetOption class objects
    #>


    [OutputType([TMAssetOption[]])]
    [CmdletBinding(DefaultParameterSetName = 'All')]
    param(
        [Parameter(Mandatory = $false)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $false)]
        [String]$Server = $global:TMSessions[$TMSession].TMServer,

        [Parameter(Mandatory = $false)]
        $AllowInsecureSSL = $global:TMSessions[$TMSession].AllowInsecureSSL,

        [Parameter(Mandatory = $false, Position = 0, ParameterSetName = 'All')]
        [Parameter(Mandatory = $true,
            Position = 0,
            ParameterSetName = 'ByType')]
        [ValidateSet(
            'Asset Environment',
            'Asset Plan Status',
            'Asset Priority',
            'Dependency Type',
            'Dependency Status',
            'App Type',
            'Asset Type',
            'App Type',
            'Task Category')]
        [String]$Type,

        [Parameter(Mandatory = $false,
            Position = 1,
            ParameterSetName = 'ByType')]
        [String]$Name,

        [Parameter(Mandatory = $false)]
        [Switch]$ResetIDs
    )

    begin {

        Import-Module PowerHTML

        ## Get Session Configuration
        $TMSessionConfig = $global:TMSessions[$TMSession]
        if (-not $TMSessionConfig) {
            throw "TM Session Not Found. Use New-TMSession command before using features."
        }

        $Instance = $Server.Replace('/tdstm', '').Replace('https://', '').Replace('http://', '')
        $Uri = "https://$instance/tdstm/assetEntity/assetOptions"

        $WebRequestSplat = @{
            Method               = 'GET'
            Uri                  = $Uri
            WebSession           = $TMSessionConfig.TMWebSession
            SkipCertificateCheck = $AllowInsecureSSL
        }

        # Make the request
        try {
            Write-Verbose "Web Request Parameters:"
            Write-Verbose ($WebRequestSplat | ConvertTo-Json -Depth 10)
            Write-Verbose "Invoking web request"
            $Response = Invoke-WebRequest @WebRequestSplat
            Write-Verbose "Response status code: $($Response.StatusCode)"
            Write-Verbose "Response Content: $($Response.Content)"
        }
        catch {
            throw $_
        }

        if ($Response.StatusCode -in 200, 204) {
            $AssetOptions = @{}
            $HTML = ConvertFrom-Html -Content $response.Content -Raw
            $AssetTypes = @(
                @{Element = 'planStatusTbodyId'; Class = 'TMAssetPlanStatus' }
                @{Element = 'priorityStatusTbodyId'; Class = 'TMAssetPriority' }
                @{Element = 'dependencyTypeTbodyId'; Class = 'TMDependencyType' }
                @{Element = 'dependencyStatusTbodyId'; Class = 'TMDependencyStatus' }
                @{Element = 'envOptionTbodyId'; Class = 'TMAssetEnvironment' }
                @{Element = 'appTypeTbodyId'; Class = 'TMAppType' }
                @{Element = 'assetTypeTbodyId'; Class = 'TMAssetType' }
                @{Element = 'taskCategoryTbodyId'; Class = 'TMTaskCategory' }
            )
            foreach ($AssetType in $AssetTypes) {
                $Result = [System.Collections.ArrayList]::new()
                $TableBody = $HTML.DocumentNode.SelectNodes("//*[contains(@id, '$($AssetType.Element)')]")
                $ChildNodes = $AssetType.Element -eq 'appTypeTableId' ? $TableBody.ChildNodes[3].ChildNodes : $TableBody.ChildNodes
                foreach ($Node in $ChildNodes) {
                    if ($Node.Attributes.Count -gt 0) {
                        if ($Node.Attributes[0].Name -eq 'id') {
                            $TypeId = $ResetIDs.IsPresent ? $null : $Node.Attributes[0].Value.Split("_")[1]
                            $TypeName = $Node.ChildNodes[1].innerText
                            $AssetOption = New-Object -TypeName $AssetType.Class -ArgumentList $TypeId, $TypeName
                            [void]$Result.Add($AssetOption)
                        }
                    }
                }

                $AssetOptions.Add($AssetType.Element.Replace('TbodyId', '').Replace('TableId', ''), $Result)
            }
        }
        else {
            throw "Unable to get Asset Options"
        }
    }

    process {
        if ($Type) {
            $AssetOptions = switch ($Type) {
                'Asset Environment' { $AssetOptions.envOption }
                'Asset Plan Status' { $AssetOptions.planStatus }
                'Asset Priority' { $AssetOptions.priorityStatus }
                'Dependency Type' { $AssetOptions.dependencyType }
                'Dependency Status' { $AssetOptions.dependencyStatus }
                'App Type' { $AssetOptions.appType }
                'Asset Type' { $AssetOptions.assetType }
                'Task Category' { $AssetOptions.taskCategory }
            }

            if ($Name) {
                $AssetOptions = $AssetOptions | Where-Object { $_.label -eq $Name }
            }
        }

        ## Reset IDs
        if ($ResetIDs) {
            for ($i = 0; $i -lt $AssetOptions.Count; $i++) {
                $AssetOptions[$i].id = $null
            }
        }

        $AssetOptions = $AssetOptions | Sort-Object -Property 'label'
        $AssetOptions
    }
}


function New-TMAssetOption {
    <#
    .SYNOPSIS
    Creates a new Asset Option in TransitionManager
 
    .DESCRIPTION
    This function will create a new Asset Option (Asset Environment, Asset Plan Status,
    Asset Priority, Dependency Type, Dependency Status, Asset Type, Task Category) on
    the specified TransitionManager instance
 
    .PARAMETER TMSession
    The name of the TM Session to use when creating the Asset Option
 
    .PARAMETER Server
    The URI of the TransitionManager instance
 
    .PARAMETER AllowInsecureSSL
    Switch indicating that insecure SSL may be used
 
    .PARAMETER Type
    The type of TransitionManager Asset Option to create
 
    .PARAMETER Name
    The Name/Label of the Asset Option
 
    .PARAMETER InputObject
    A TMAssetOption object representing the Asset Option to create
 
    .PARAMETER Passthru
    Switch indicating that the newly created Asset Option should be returned
 
    .EXAMPLE
    New-TMAssetOption -TMSession 'tdsmd06' -Type 'Asset Priority' -Name 'Critical' -Passthru
 
    .EXAMPLE
    $AssetType = [TMAssetType]::new('Server')
    New-TMAssetOption -InputObject $AssetType
 
    .EXAMPLE
    New-TMSession -ProfileName 'tmddev'
    New-TMSession -ProfileName 'tmddev2'
    Get-TMAssetOption -TMSession 'tmddev' -Type 'Asset Plan Status' | New-TMAssetOption -TMSession 'tmddev2'
 
    .OUTPUTS
    A TMAssetOption object if the Passthru switch is used, otherwise nothing
    #>


    [CmdletBinding(DefaultParameterSetName = 'ByProperty')]
    param(
        [Parameter(Mandatory = $false)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $false)]
        [String]$Server = $global:TMSessions[$TMSession].TMServer,

        [Parameter(Mandatory = $false)]
        $AllowInsecureSSL = $global:TMSessions[$TMSession].AllowInsecureSSL,

        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateSet(
            'Asset Environment',
            'Asset Plan Status',
            'Asset Priority',
            'Dependency Type',
            'Dependency Status',
            'App Type',
            'Asset Type',
            'App Type',
            'Task Category')]
        [String]$Type,

        [Parameter(Mandatory = $true,
            Position = 1,
            ParameterSetName = 'ByProperty')]
        [Alias('Label')]
        [String]$Name,

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ParameterSetName = 'ByObject')]
        [TMAssetOption]$InputObject,

        [Parameter(Mandatory = $false)]
        [Switch]$Passthru
    )

    begin {
        ## Get Session Configuration
        $TMSessionConfig = $global:TMSessions[$TMSession]
        if (-not $TMSessionConfig) {
            throw "TM Session Not Found. Use New-TMSession command before using features."
        }

        $Instance = $Server.Replace('/tdstm', '').Replace('https://', '').Replace('http://', '')
        $Uri = "https://$instance/tdstm/assetEntity/saveAssetoptions"

        Set-TMHeaderContentType -ContentType 'Form' -TMSession $TMSession
    }

    process {
        if ($PSCmdlet.ParameterSetName -eq 'ByObject') {
            $Type = switch ($InputObject.GetType().Name) {
                'TMAssetEnvironment' { 'Asset Environment' }
                'TMAssetPlanStatus' { 'Asset Plan Status' }
                'TMAssetPriority' { 'Asset Priority' }
                'TMDependencyType' { 'Dependency Type' }
                'TMDependencyStatus' { 'Dependency Status' }
                'TMAssetType' { 'App Type' }
                'TMAssetType' { 'Asset Type' }
                'TMTaskCategory' { 'Task Category' }
                default {
                    Write-Error "The type of Asset Option could not be determined"
                    return
                }
            }
            $Name = $InputObject.label
        }

        switch ($Type) {
            'Asset Environment' { $Class = 'TMAssetEnvironment'; $PostBody = @{environment = $Name; assetOptionType = 'environment' } }
            'Asset Plan Status' { $Class = 'TMAssetPlanStatus'; $PostBody = @{planStatus = $Name; assetOptionType = 'planStatus' } }
            'Asset Priority' { $Class = 'TMAssetPriority'; $PostBody = @{priorityOption = $Name; assetOptionType = 'Priority' } }
            'Dependency Type' { $Class = 'TMDependencyType'; $PostBody = @{dependencyType = $Name; assetOptionType = 'dependency' } }
            'Dependency Status' { $Class = 'TMDependencyStatus'; $PostBody = @{dependencyStatus = $Name; assetOptionType = 'dependencyStatus' } }
            'App Type' { $Class = 'TMAppType'; $PostBody = @{appType = $Name; assetOptionType = 'appType' } }
            'Asset Type' { $Class = 'TMAssetType'; $PostBody = @{assetType = $Name; assetOptionType = 'assetType' } }
            'Task Category' { $Class = 'TMTaskCategory'; $PostBody = @{taskCategory = $Name; assetOptionType = 'taskCategory' } }
        }

        $WebRequestSplat = @{
            Method               = 'POST'
            Uri                  = $Uri
            WebSession           = $TMSessionConfig.TMWebSession
            SkipCertificateCheck = $AllowInsecureSSL
            Body                 = $PostBody
        }

        # Make the request
        try {
            Write-Verbose "Web Request Parameters:"
            Write-Verbose ($WebRequestSplat | ConvertTo-Json -Depth 10)
            Write-Verbose "Invoking web request"
            $Response = Invoke-WebRequest @WebRequestSplat
            Write-Verbose "Response status code: $($Response.StatusCode)"
            Write-Verbose "Response Content: $($Response.Content)"
        }
        catch {
            throw $_
        }

        if ($Response.StatusCode -in 200, 204) {
            $ResponseContent = $Response.Content | ConvertFrom-Json
            if ($ResponseContent.status -eq "error") {
                if ($ResponseContent.errors[0] -notlike 'Property value with value * must be unique') {
                    Write-Error $ResponseContent.errors[0]
                }
            }
            elseif ($Passthru) {
                New-Object -TypeName $Class -ArgumentList $ResponseContent.id, $Name
            }
        }
    }
}


function Remove-TMAssetOption {
    <#
    .SYNOPSIS
    Deletes an Asset Option from TransitionManager
 
    .DESCRIPTION
    This function will delete an Asset Option (Asset Environment, Asset Plan Status,
    Asset Priority, Dependency Type, Dependency Status, Asset Type, Task Category) from
    the specified TransitionManager instance
 
    .PARAMETER TMSession
    The name of the TM Session to use when deleting the Asset Option
 
    .PARAMETER Server
    The URI of the TransitionManager instance
 
    .PARAMETER AllowInsecureSSL
    Switch indicating that insecure SSL may be used
 
    .PARAMETER Type
    The type of TransitionManager Asset Option to delete
 
    .PARAMETER Name
    The NAme of the Asset Option to delete
 
    .PARAMETER Id
    The Id of the Asset Option to delete
 
    .PARAMETER InputObject
    A TMAssetOption object representing the Asset Option to remove
 
    .EXAMPLE
    Get-TMAssetOption -Type 'Asset Environment' | Remove-TMAssetOption
 
    .EXAMPLE
    Remove-TMAssetOption -TMSession 'tmddev' -Type 'Dependency Type' -Name 'A2A'
 
    .OUTPUTS
    None
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [String]$TMSession = "Default",

        [Parameter(Mandatory = $false)]
        [String]$Server = $global:TMSessions[$TMSession].TMServer,

        [Parameter(Mandatory = $false)]
        $AllowInsecureSSL = $global:TMSessions[$TMSession].AllowInsecureSSL,

        [Parameter(Mandatory = $true,
            Position = 0,
            ParameterSetName = 'ByName')]
        [Parameter(Mandatory = $true,
            Position = 0,
            ParameterSetName = 'ById')]
        [ValidateSet(
            'Asset Environment',
            'Asset Plan Status',
            'Asset Priority',
            'Dependency Type',
            'Dependency Status',
            'Asset Type',
            'App Type',
            'Task Category')]
        [String]$Type,

        [Parameter(Mandatory = $true,
            Position = 1,
            ParameterSetName = 'ByName')]
        [Alias('Label')]
        [String]$Name,

        [Parameter(Mandatory = $true,
            Position = 1,
            ParameterSetName = 'ById')]
        [String]$Id,

        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true,
            ParameterSetName = 'ByObject')]
        [TMAssetOption]$InputObject
    )

    begin {
        ## Get Session Configuration
        $TMSessionConfig = $global:TMSessions[$TMSession]
        if (-not $TMSessionConfig) {
            throw "TM Session Not Found. Use New-TMSession command before using features."
        }

        $Instance = $Server.Replace('/tdstm', '').Replace('https://', '').Replace('http://', '')
        $Uri = "https://$instance/tdstm/assetEntity/deleteAssetOptions"

        Set-TMHeaderContentType -ContentType 'Form' -TMSession $TMSession
    }

    process {
        if ($PSCmdlet.ParameterSetName -eq 'ByObject') {
            $Type = switch ($InputObject.GetType().Name) {
                'TMAssetEnvironment' { 'Asset Environment' }
                'TMAssetPlanStatus' { 'Asset Plan Status' }
                'TMAssetPriority' { 'Asset Priority' }
                'TMDependencyType' { 'Dependency Type' }
                'TMDependencyStatus' { 'Dependency Status' }
                'TMAssetType' { 'Asset Type' }
                'TMTaskCategory' { 'Task Category' }
            }
            $Name = $InputObject.label
            $Id = $InputObject.id
        }

        # Get the Id if it wasn't provided
        if (($null -eq $Id) -or ($Id -le 0)) {
            $AssetOption = Get-TMAssetOption -TMSession $TMSession -Type $Type -Name $Name
            if ($AssetOption) {
                $Id = $AssetOption.id
            }
            else {
                # There is no asset option, so there's nothing to remove
                return
            }
        }

        # Format the request form body
        $PostBody = switch ($Type) {
            'Asset Environment' { @{ environmentId = $Id; assetOptionType = 'environment' } }
            'Asset Plan Status' { @{ assetStatusId = $Id; assetOptionType = 'planStatus' } }
            'Asset Priority' { @{ priorityId = $Id; assetOptionType = 'Priority' } }
            'Dependency Type' { @{ dependecyId = $Id; assetOptionType = 'dependency' } }
            'Dependency Status' { @{ dependecyId = $Id; assetOptionType = 'dependencyStatus' } }
            'Asset Type' { @{ assetTypeId = $Id; assetOptionType = 'assetType' } }
            'Task Category' { @{ taskCategoryId = $Id; assetOptionType = 'taskCategory' } }
        }

        # Format the web request
        $WebRequestSplat = @{
            Method               = 'POST'
            Uri                  = $Uri
            WebSession           = $TMSessionConfig.TMWebSession
            SkipCertificateCheck = $AllowInsecureSSL
            Body                 = $PostBody
        }

        # Make the web request
        try {
            Write-Verbose "Web Request Parameters:"
            Write-Verbose ($WebRequestSplat | ConvertTo-Json -Depth 10)
            Write-Verbose "Invoking web request"
            $Response = Invoke-WebRequest @WebRequestSplat
            Write-Verbose "Response status code: $($Response.StatusCode)"
            Write-Verbose "Response Content: $($Response.Content)"
        }
        catch {
            Write-Error $_
        }

        # Process the response
        if ($Response.StatusCode -in 200, 204) {
            $ResponseContent = $Response.Content | ConvertFrom-Json
            if ($ResponseContent.status -eq "error") {
                Write-Error $ResponseContent.errors[0]
            }
        }
    }
}