public/Version/Trace-Version.ps1

using module '..\..\modules\Enums.psm1'
using module '..\..\modules\VersionChecker.psm1'

# TODO test
function Trace-Version {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        $versions,
        [ENVIRONMENT[]]$environment,
        [MODULE[]]$module,
        [RELEASE]$diff = [RELEASE]::Build)

    $_extVersions = @()
    $_naVersions = @()
    # Prepare the input versions for analysis
    foreach ($_item in $versions) {
        $_cond = ($null -eq $environment -or $_item.env -in $environment) -and ($null -eq $module -or $_item.module -in $module)
        if ($_item.version -eq 'NA' -or $_item.version -eq ''){
            if ($_cond) { $_naVersions += $_item }
        }
        else {
            if ($_cond) { $_extVersions += $_item }
        }

        if ($_cond){
            $_subModules = @()
            foreach ($_prop in $_item.PSobject.Properties) {
                if (-not ($_prop.name -in @('operator', 'brand', 'env', 'module', 'version'))) {
                    $_subModules += $_prop.name
                }
            }

            foreach ($_sub in $_subModules) {
                if (($_item.$_sub) -ne 'NA' -and ($_item.$_sub) -ne ''){
                    $_item2 = Copy-Object $_item
                    $_item2.Module = $_item2.Module + '-' + $_sub
                    $_item2.Version = $_item.$_sub

                    $_extVersions += $_item2
                }
            }
        }
    }

    $_modules = @{}
    # Group the information by modules
    foreach ($_item in $_extVersions) {
        Write-Debug "Item: $_item"
        if ($_item.Version -ne 'NA'){
            if (-not $_modules[$_item.Module]) {
                Write-Verbose 'Adding'
                $_modules.Add($_item.Module, @($_item.Version, $_item.Version))
            }
            else {
                Write-Verbose "Item: $($_item.Version), Min: $($_modules[$_item.Module][0]), Max: $($_modules[$_item.Module][1])"

                if ((Compare-Versions $_item.Version $_modules[$_item.Module][0]) -eq -1) {
                    $_modules[$_item.Module][0] = $_item.Version
                    Write-Verbose "Updated: Min: $($_modules[$_item.Module][0]), Max: $($_modules[$_item.Module][1])"
                }
                if ((Compare-Versions $_item.Version $_modules[$_item.Module][1]) -eq 1) {
                    $_modules[$_item.Module][1] = $_item.Version
                    Write-Verbose "Updated: Min: $($_modules[$_item.Module][0]), Max: $($_modules[$_item.Module][1])"
                }
            }
        }
    }

    $_operator = @{}
    # Group the information by operator
    foreach ($_item in $_extVersions) {
        if ($_item.version -ne 'NA'){
            $_diff = (Compare-Release $_item.version $_modules[$_item.Module][1])

            if (-not $_operator[$_item.operator]) {
                $_operator.Add($_item.operator, @{$_item.brand = @{ $_item.env = @{$_item.module = $_diff }}})
            }
            elseif (-not $_operator[$_item.operator][$_item.brand]) {
                $_operator[$_item.operator].Add($_item.brand, @{ $_item.env = @{$_item.module = $_diff }})
            }
            elseif (-not $_operator[$_item.operator][$_item.brand][$_item.env]) {
                $_operator[$_item.operator][$_item.brand].Add($_item.env, @{$_item.module = $_diff })
            }
            elseif (-not $_operator[$_item.operator][$_item.brand][$_item.env][$_item.module]) {
                $_operator[$_item.operator][$_item.brand][$_item.env].Add($_item.module, $_diff )
            }
        }
    }

    Write-Host
    Write-Host 'Baseline:'
    Write-Host '*********'
    if ($_modules.Count -gt 0){
        foreach ($_mod in $_modules.GetEnumerator()) {
            $_env = [ENVIRONMENT]::DEV
            foreach ($_ver in $_extVersions) {
                if (($_mod.Name -eq $_ver.Module) -and ($_mod.Value[1] -eq $_ver.version)) {
                    if ((Compare-Environments $_ver.env $_env) -eq -1) { $_env = $_ver.env }
                }
            }
            Write-Host "* $($_mod.Name.PadRight(13,' ')) v$($_mod.Value[1].PadRight(10,' ')) $_env"
        }
    }
    else {
        Write-host "No results!"
    }

    Write-Host
    Write-Host 'Operator analysis:'
    Write-Host '******************'
    if ($_modules.Count -gt 0){
        foreach ($_op in $_operator.GetEnumerator()) {
            [RELEASE]$_diffOp = [RELEASE]::None

            foreach ($_brand in $_op.Value.GetEnumerator()) {
                [RELEASE]$_diffBrand = [RELEASE]::None

                foreach ($_env in $_brand.Value.GetEnumerator()) {
                    [RELEASE]$_diffEnv = [RELEASE]::None
                    foreach ($_mod in $_env.Value.GetEnumerator()) {
                        Write-Verbose "Module: $($_mod.Name), Value: $($_mod.Value)"
                        if ($_mod.Value -gt $_diffEnv) {$_diffEnv = $_mod.Value}
                    }
                    if ($_brand.Name) {
                        $_key = "$($_op.Name)-$($_brand.Name) @ $($_env.Name)"
                    }
                    else {
                        $_key = "$($_op.Name) @ $($_env.Name)"
                    }
                    if ($diff -le $_diffEnv){
                        Write-Host ('* ' + $_key.PadRight(16,' ')) -NoNewline
                        Write-Host $_diffEnv -ForegroundColor (Get-Color $_diffEnv)

                        foreach ($_mod in $_env.Value.GetEnumerator()) {
                            #Write-Host "$($_mod.Name) v$($_modules[$_mod.Name][1])"
                            if ($diff -le [RELEASE]::None) {
                                Write-Versions -versions $_extVersions -operator $_op.Name -brand $_brand.Name -env $_env.Name -module $_mod.Name `
                                        -latestVersion $_modules[$_mod.Name][1] -release None -prefix ' # '
                            }
                            if ($diff -le [RELEASE]::Build) {
                                Write-Versions -versions $_extVersions -operator $_op.Name -brand $_brand.Name -env $_env.Name -module $_mod.Name `
                                        -latestVersion $_modules[$_mod.Name][1] -release Build -prefix ' # '
                            }
                            if ($diff -le [RELEASE]::Patch) {
                                Write-Versions -versions $_extVersions -operator $_op.Name -brand $_brand.Name -env $_env.Name -module $_mod.Name `
                                        -latestVersion $_modules[$_mod.Name][1] -release Patch -prefix ' # '
                            }
                            if ($diff -le [RELEASE]::Minor) {
                                Write-Versions -versions $_extVersions -operator $_op.Name -brand $_brand.Name -env $_env.Name -module $_mod.Name `
                                        -latestVersion $_modules[$_mod.Name][1] -release Minor -prefix ' # '
                            }
                            if ($diff -le [RELEASE]::Major) {
                                Write-Versions -versions $_extVersions  -operator $_op.Name -brand $_brand.Name -env $_env.Name -module $_mod.Name `
                                    -latestVersion $_modules[$_mod.Name][1] -release Major -prefix ' # '
                            }
                        }
                    }
                    if ($_diffEnv -gt $_diffBrand) {$_diffBrand = $_diffEnv}
                }

                if ($_diffBrand -gt $_diffOp) {$_diffOp = $_diffBrand}
            }
        }
    }
    else {
        Write-host "No results!"
    }

    Write-Host
    Write-Host 'Module analysis:'
    Write-Host '****************'
    if ($_modules.Count -gt 0){
        foreach ($_mod in $_modules.GetEnumerator()) {

            $_actualDiff = (Compare-Release $_mod.Value[0] $_mod.Value[1])

            if ($diff -le $_actualDiff) {
                $_bgcolor = (Get-Color $_actualDiff)

                Write-Host ('* ' + $_mod.Name.PadRight(19, ' ')) -NoNewline
                Write-Host (' v' + $_mod.Value[1].PadRight(10,' ')) -ForegroundColor $_bgcolor -NoNewline
                Write-Host "($_actualDiff)" -ForegroundColor $_bgcolor

                if ($diff -le [RELEASE]::None) {
                    Write-Versions -versions $_extVersions -module $_mod.Name -latestVersion $_mod.Value[1] -release None -prefix ' # ' -moduleAnalysis
                }
                if ($diff -le [RELEASE]::Build) {
                    Write-Versions -versions $_extVersions -module $_mod.Name -latestVersion $_mod.Value[1] -release Build -prefix ' # ' -moduleAnalysis
                }
                if ($diff -le [RELEASE]::Patch) {
                    Write-Versions -versions $_extVersions -module $_mod.Name -latestVersion $_mod.Value[1] -release Patch -prefix ' # ' -moduleAnalysis
                }
                if ($diff -le [RELEASE]::Minor) {
                    Write-Versions -versions $_extVersions -module $_mod.Name -latestVersion $_mod.Value[1] -release Minor -prefix ' # ' -moduleAnalysis
                }
                if ($diff -le [RELEASE]::Major) {
                    Write-Versions -versions $_extVersions -module $_mod.Name -latestVersion $_mod.Value[1] -release Major -prefix ' # ' -moduleAnalysis
                }
            }
        }
    }
    else {
        Write-host "No results!"
    }

    Write-Host
    Write-Host 'NA versions:'
    Write-Host '************'
    if ($_naVersions.Count -gt 0){
        foreach ($_ver in $_naVersions) {
            # $_env = [ENVIRONMENT]::DEV
            # if ($_ver.env -gt $_env) { $_env = $_ver.env}

            if ($_ver.brand){
                $_text = [string]$_ver.operator + '-' + $_ver.brand + ' @ ' + [string]$_ver.env
            }
            else {
                $_text = [string]$_ver.operator + ' @ ' + [string]$_ver.env
            }
            Write-Host "* $($_ver.module.PadRight(5,' ')) $_text"
        }
    }
    else{
        Write-host "No results!"
    }
    Write-Host
}