RiverMeadow.Development.Organization/RiverMeadow.Development.Organization.psm1

using module '../Common/Result'
Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Util | Join-Path -ChildPath Util)
Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Common | Join-Path -ChildPath Common)
Import-Module -Name @(Join-Path $PSScriptRoot .. | Join-Path -ChildPath Common | Join-Path -ChildPath Wrappers | Join-Path -ChildPath Wrappers)
function Switch-RMProject {
    param(
        [Alias("on")]
        [string] $OrganizationName,
        [Alias("pn")]
        [string] $ProjectName
    )
    try {
        $LoginStatus = Test-UserLoggedIn
        if ($LoginStatus.ReturnCode -eq [RMReturn]::ERROR) {
            return $LoginStatus
        }

        [RMReturn] $RMReturn = [RMReturn]::new()
        $OrgsAndProjectsMap = (Get-RMUserOrgAndProjectAsHashtable)[1]
        if ([string]::IsNullOrEmpty($OrganizationName) -and [string]::IsNullOrEmpty($ProjectName)) {
            Write-Output "User's Organizations and Projects:" | Out-Host
            (Get-Variable -Name "RMContext-UserOrganizations").Value | Format-Table @{Label="Organization Name"; Expression={if (!$_.is_project) { $_.name}else{ ""}}}, `
                @{Label="Project Name"; Expression={if ($_.is_project){$_.name}else{""}}} -AutoSize -Wrap | Out-Host
            $RMReturn.SetOutputData(@{"User_Orgs_Projects" = $OrgsAndProjectsMap;})
            $RMReturn.SetReturnCode([RMReturn]::SUCCESS)
            return $RMReturn
        }

        $Errors = Confirm-RMUserInput -OrganizationName $OrganizationName -ProjectName $ProjectName -UserOrgAndProject $OrgsAndProjectsMap
        if ($Errors.Count -gt 0) {
            Out-RMUserParameterResult -ErrorMessage $Errors
            Add-RMErrorAndWarning -RMReturnObject $RMReturn -ErrorMessage $Errors
            return $RMReturn
        }
    
        $ProjectObj = Get-RMProjectByName -OrganizationName $OrganizationName -ProjectName $ProjectName
    
        $Uri = Get-Variable -Name "RMContext-ReactorURI"

        $RMLoginResult = Get-Variable -Name "RMContext-UserLogin"
        $Headers = @{
            Accept = "application/rm+json"
            "X-Auth-Token" = $RMLoginResult.Value.token
        }
    
        $Params = @{
            Method = "Put"
            Uri = $Uri.Value + "/users/" + $RMLoginResult.Value.user_id + "/organization/" + $ProjectObj.id + "/switch"
            Headers = $Headers
        }
    
        Invoke-RMRestMethod -Params $Params | Out-Null
    
        Set-Variable -Name "RMContext-CurrentOrganizationName" -Value $OrganizationName -Scope Global
        Set-Variable -Name "RMContext-CurrentParentOrganizationId" -Value $ProjectObj.parent_organization_id -Scope Global
    
        Set-Variable -Name "RMContext-CurrentProjectName" -Value $ProjectName -Scope Global
        Set-Variable -Name "RMContext-CurrentProjectId" -Value $ProjectObj.id -Scope Global
    
        Write-Output "Current organization set to: $OrganizationName" | Out-Host
        Write-Output "Current project set to: $ProjectName" | Out-Host

        $RMReturn.SetReturnCode([RMReturn]::SUCCESS)
        $RMReturn.SetOutputData(@{"Current_Organization" = $OrganizationName; "Current_Project" = $ProjectName;})
        return $RMReturn
    } catch {
        Show-RMError -ErrorObj $PSItem
        return Build-RMError -ErrorObj $PSItem
    }
}

function Confirm-RMUserInput {
    param(
        [string] $OrganizationName,
        [string] $ProjectName,
        [hashtable] $UserOrgAndProject
    )
    $Errors = @()
    if ([string]::IsNullOrEmpty($OrganizationName) -and ![string]::IsNullOrEmpty($ProjectName)) {
        $Errors += "Please provide the Organization Name"
    }

    if (![string]::IsNullOrEmpty($OrganizationName) -and [string]::IsNullOrEmpty($ProjectName)) {
        $Errors += "Please provide the Project Name"
    }

    if (![string]::IsNullOrEmpty($OrganizationName)) {
        if (!$UserOrgAndProject.ContainsKey($OrganizationName)) {
            $Errors += "Organization '$OrganizationName' does not exist"
        } elseif (![string]::IsNullOrEmpty($ProjectName) -and !$UserOrgAndProject[$OrganizationName].Contains($ProjectName)) {
            $Errors += "Project '$ProjectName' does not exist"
        }
    }

    return $Errors
}

function Get-RMProjectByName {
    param(
        [string] $OrganizationName,
        [string] $ProjectName
    )

    $UserOrgs = (Get-Variable -Name "RMContext-UserOrganizations").Value
    $OrgFound = $false
    foreach ($UserOrg in $UserOrgs) {
        if ($UserOrg.name -eq $OrganizationName) {
            $OrgFound = $true
            continue
        }

        # Default project is present in all Orgs, so we need to
        # make sure that the org is found and only then check
        # the project. The Data returned by FE is ordered by Org
        # followed by the projects of the Org; so we expect to find
        # Org first.
        if ($OrgFound -and $UserOrg.name -eq $ProjectName) {
            return $UserOrg
        }
    }

    return $null
}

function Get-RMUserOrgAndProjectAsHashtable {
    $UserOrgs = (Get-Variable -Name "RMContext-UserOrganizations").Value

    $OrgsAndProjectsMap = @{}
    $CurrentOrg
    foreach($UserOrg in $UserOrgs) {
        if (!$UserOrg.is_project) {
            $CurrentOrg = $UserOrg.name
            $OrgsAndProjectsMap.Add($UserOrg.name, @())
            continue
        }
        $OrgProjects = $OrgsAndProjectsMap[$CurrentOrg]
        $OrgProjects += $UserOrg.name
        $OrgsAndProjectsMap[$CurrentOrg] = $OrgProjects
    }
    return $OrgsAndProjectsMap
}

Export-ModuleMember -Function Switch-RMProject