src/tools/functions/functions.ps1

$modulePath = (Get-Item $PSScriptRoot).Parent.Parent.FullName
$debug = $true
$hvalue = [Environment]::GetEnvironmentVariable("ZSESSIONID", "User")
$header = @{"zsessionid"=$hvalue}

function dsFolderPath(){ 
    [Environment]::GetEnvironmentVariable("DS_FOLDER_PATH", "User")
}
function dsDataToUUID(){
    param(
        [Parameter(ValueFromPipeline)] $dsData
    )
    $dsData.QueryResult.Results[0]._refObjectUUID
}
function dsDataToName(){
    param(
        [Parameter(ValueFromPipeline)] $dsData
    )
    $dsData.QueryResult.Results[0]._refObjectName
}
function dsDataToRefUrl(){
    param(
        [Parameter(ValueFromPipeline)] $dsData
    )
    $dsData.QueryResult.Results[0]._ref
}
function getDsDataFromDsId($dsId){
    Invoke-RestMethod -Uri "https://rally1.rallydev.com/slm/webservice/v2.0/DefectSuite?query=(FormattedID = $dsId)" -Headers $header | Select-Object QueryResult 
}
function getDsFullFromRefUrl(){
    param(
        [Parameter(ValueFromPipeline)] $refUrl
    )
    Invoke-RestMethod -Uri $refUrl -Headers $header | Select-Object DefectSuite
} 
# TODO: Create DS folder in dsFolderPath, create _index.md and write Ds content in there
# TODO: Log operations to a file in the root dsFolderPath
function createDsFolder(){
    param([Parameter(ValueFromPipeline)] $dsFullData)
    throw NotImplementedException
}
function postDefect(){
    param(
        [Parameter(ValueFromPipeline)] $defect
    )
    if($debug){
        $defect | defectToYamlFile
        Write-Output "Would have posted this defect: $($defect | ConvertTo-Json -Depth 3)"
        return
    }else{
        Invoke-RestMethod -Method Post -Uri "https://rally1.rallydev.com/slm/webservice/v2.0/defect/create" -Headers $header -Body $defect
    }
}
function getDsFolder(){
    param(
        [Parameter(ValueFromPipeline)] $dsId
    )
    $directories = Get-ChildItem -Path dsFolderPath -Directory -Filter "$dsId*"
    if($directories.Length -gt 1){
        Write-Error "There are duplicate directories for this DefectSuite."
    }
    return $directories[0]
}
function getDsDefects(){
    param(
        [Parameter(ValueFromPipeline)] $dsObjectID
    )
    $url = "https://rally1.rallydev.com/slm/webservice/v2.0/DefectSuite/$dsObjectID/Defects"
    # Write-Output "Invoking request: $url"
    (Invoke-RestMethod -Uri $url -Headers $header).QueryResult.Results 
    | Select-Object FormattedID,Name,Description,c_ApprovedProject,c_FoundinVersion,c_VerifiedinVersion,c_Impact,c_Likelihood,Priority,c_Product,c_Activity,c_Workaround,Environment,SalesforceCaseNumber,Severity,State,Project,DefectSuites,Expedite,DisplayColor
}
function dsFullToDefect(){
    param(
        [Parameter(ValueFromPipeline)] $dsFull
    )
    $dsFull | ConvertTo-Yaml | Out-File "$(dsFolderPath)/DefectSuite.yml"
    $ds = $dsFull.DefectSuite
    $approvedProject = if($ds.Name.Contains("QQCatalyst")){
        "QQCatalyst"
    }elseif($ds.Name.Contains("AMS360")){
        "AMS360"
    }else{
        ""
    }
    
    $ds | ConvertTo-Yaml | Out-File "$(dsFolderPath)/Defect.yml"
    $ds | ConvertTo-Json -Depth 3 | Write-Output
    @{
        Name = $ds.Name
        Description = $ds.Description
        c_ApprovedProject = $approvedProject
        c_FoundinVersion = $ds.c_FoundinVersion
        c_VerifiedinVersion = $ds.c_VerifiedinVersion
        c_Impact = $ds.c_Impact
        c_Likelihood = $ds.c_Likelihood
        Priority = $ds.Priority
        c_Product = $ds.c_Product
        c_Activity = $ds.c_Activity
        c_Workaround = $ds.c_Workaround
        Environment = $ds.Environment
        SalesforceCaseNumber = $ds.SalesforceCaseNumber
        Severity = $ds.Severity
        State = $ds.State
        Project = $ds.Project
        DefectSuites = @($ds.FormattedID)
        Expedite = $ds.Expedite
        DisplayColor = $ds.DisplayColor
    }
}
function getVersion(){
    $manifestPath = "$modulePath/RallyQuickToolsCli.psd1"
    $content = Get-Content $manifestPath -Raw
    $version = (
        $content `
        | Select-String "(?<=ModuleVersion = ').*(?=')"
    ).Matches.Value.Split('.')
    return $version
}
function getLatestVersion(){
    ((Invoke-WebRequest -Uri "https://www.powershellgallery.com/packages/RallyQuickToolsCli" -Method Head).BaseResponse.RequestMessage.RequestUri.AbsolutePath -Split "/")[-1].Split('.')
}
function trimName(){
    param(
        [string] $name
    )
    if($name.IndexOfAny(":") -gt -1){
        $name = ($name -split ":")[1]
    }else{
        $dsNameArray = $name -split "-"
        if($dsNameArray.Length -gt 1){
            $name = $dsNameArray[-1].Trim()
        }
    }
    $name = ($($name) -replace "[ #/]","_" -replace "QQCatalyst","_" -replace "Support","_" -replace "_{2,10}", "_" ).Trim("_")
    $name = $name.Substring(0, [System.Math]::Min(50, $name.Length -1))
    $name = $name.Substring(0, (@(50, $name.LastIndexOf("_"), $name.Length) | Measure-Object -Minimum).Minimum -1)
    $name
}
function defectResponseToDefect(){
    param(
        [Parameter(ValueFromPipeline)][String] $dr
    )
    return $dr 
    | Select-Object Name,Description,c_ApprovedProject,c_FoundinVersion,c_VerifiedinVersion,c_Impact,c_Likelihood,Priority,c_Product,c_Activity,c_Workaround,Environment,SalesforceCaseNumber,Severity,State,Project,DefectSuites,Expedite,DisplayColor
}
function dsFullToYamlFile(){
    param(
        [Parameter(ValueFromPipeline)] $dsFull
    )
    $ds = $dsFull.DefectSuite
    $dsName = trimName($ds.Name)
    Write-Output "DsName: $dsName"
    $dsId = $($ds.FormattedID)
    $dsIdFolder = "$(dsFolderPath)/$dsId-$dsName"
    if(-not(Test-Path $dsIdFolder -PathType Container)){
        Write-Output "Creating directory: $dsIdFolder/"
        New-Item "$dsIdFolder" -ItemType Directory
    }
    $outFile = "$dsIdFolder/dsInfo.yml"
    Write-Output "Writing to: $outFile"
    $ds | ConvertTo-Yaml | Out-File $outFile -Force
    if(-not(Test-Path "$dsIdFolder/_index.md")){
        "# $dsName`n`n[$dsName]($($ds._ref))`n`n" `
        + $ds.Description `
        -replace "<p>&nbsp;</p>","" `
        -replace "<p>","" `
        -replace "</p>","`n" `
        -replace "`n{3,100}","`n`n" `
        | Out-File "$dsIdFolder/_index.md"
        
    }
}
function defectToYamlFile(){
    param(
        [Parameter(ValueFromPipeline)] $defect
    )
    $outFile = "$(dsFolderPath)/defect.yml"
    Write-Output "Writing to: $outFile"
    $defect | ConvertTo-Yaml | Out-File $outFile -Force
}
function wrapWithHtml($linkUrl, $textText){
    return "
    <html>
    <body>
    <!--StartFragment-->
    <a href='$linkUrl'>$linkText</a>
    <!--EndFragment-->
    </body>
    </html>"

}
function mapToDevDefect(){
    param(
        [Parameter(ValueFromPipeline)] $defect
    )
    $defect.Name = "$($defect.FormattedID) - Dev - $($defect.Name)"
    Write-Information "modifyDefect: $defect"
    return $defect
}


function updateDsToSre(){
    param(
        [Parameter(ValueFromPipeline)] $ds
    )
    <#
        2. The Defect Suite's "SRE SLA Date" will be updated to 90 days from the time you click the button to fit with our SLA.
        3. The Defect Suite's "Escalation Status" will be set to "Waiting for Analysis".
    #>

    $ds.EscalationStatus = "Waiting for Analysis"
    $ds.SreSlaDate = [System.DateTime]::Now.AddDays(90)
    Write-Information "updateDsToSre: $ds"
    return $ds
}
function updateDsToDev(){
    param(
        [Parameter(ValueFromPipeline)] $ds
    )
    <#
        3. The Defect Suite will be updated to:
            a. Remove the current owner
            b. Update its status to the most relevant "waiting" option. (i.e."In analysis" => "Waiting for analysis" and "Remediation in progress" => "Waiting for remediation")
            c. Add the "DivertedToDev" tag
    #>

    $ds.Owner = null
    $ds.EscalationStatus = "Waiting for analysis"
    $ds.Tags = @($ds.Tags, "DivertedToDev")
    Write-Information "updateDsToDev: $ds"
    return $ds
}
function updateDsToSreAndDev(){
    param(
        [Parameter(ValueFromPipeline)] $ds
    )
    <#
        3. The Defect Suite will be updated to:
            a. Remove the current owner
            b. Update its status to the most relevant "waiting" option. (i.e."In analysis" => "Waiting for analysis" and "Remediation in progress" => "Waiting for remediation")
            c. Add the "DivertedToDev" tag
    #>

    $ds.Owner = null
    $ds.EscalationStatus = "Waiting for analysis"
    $ds.Tags = @($ds.Tags, "DivertedToDev")
    Write-Information "updateDsToSreAndDev: $ds"
    return $ds
}
function updateExistingSreDefect(){
    param(
        [Parameter(ValueFromPipeline)] $ds
    )
    <#
        1. Attempt to find the existing SRE defect and update its: "State" to "Closed" and "Schedule State" to "Accepted" and "Resolution" to "Duplicate". (If none exists it should throw an exception and do nothing else as a safety.)
    #>

    $defect = $ds.ObjectID | getDsDefects | Select-Object -First 1
    $defect.State = "Closed"
    $defect.ScheduleState = "Accepted"
    $defect.Resolution = "Duplicate"
    Write-Information "updateExistingSreDefect: $defect"
    
    return $ds
}


function mapToSreDefect(){
    param(
        [Parameter(ValueFromPipeline)] $defect
    )
    <#
        a. The new Defect will have the following name structure: DS#### - SRE - Defect Suite Title
        b. The new Defect will be assigned to the Site Reliability Project.
        c. The new Defect will be attached to the Defect Suite.
    #>

    $defect.Name = "$($defect.FormattedID) - SRE - $($defect.Name)"
    $defect.Project = "Site Reliability Project"
    # $defect.DefectSuites = @($($defect.DefectSuites) | Select-Object -ExpandProperty Name)
    Write-Information "modifyDefect: $defect"
    return $defect
}
function mapDefect(){
    param(
        [Parameter(ValueFromPipeline, Position=0)] $defect,
        [Parameter(ValueFromPipeline=$false, Position=1)][alias("t")] $target
    )
    $defect.Name = "$($defect.FormattedID) - $target - $($defect.Name)"
    Write-Information "modifyDefect: $defect"
    return $defect
}