public/Market/Find-Markets.ps1

using module '..\..\modules\Enums.psm1'
using module '..\..\modules\Helper\DateTimeHelper.psm1'
using module '..\..\modules\Helper\StringHelper.psm1'
using module '..\..\modules\Helper\ObjectHelper.psm1'
using module '..\..\modules\Session.psd1'

# TODO rethink
# TODO Test
function Find-Markets{
    [CmdletBinding()]
    [Alias('fm')]
    param(
        # source file
        [Parameter(Mandatory=$true)]
        [SOURCE]$source,
        [ValidateSet('all', 'mutable', 'immutable', 'mapped', 'unmapped', 'wrong-definition')]
        # condition for filtering
        [string]$condition='all',
        [ValidateSet('context', 'changes')]
        # sorting preference
        [string]$sortBy='context',
        [string]$marketDefinitonsFile
    )

    #region Validations

    if ([Session]::activeSessions.Count -eq 0){
        Write-Error 'There is no active session. Import audit logs before they are analyzed.'
        return
    }

    if ($condition -in ('unmapped')){
        if ($source -in ([SOURCE]::core, [SOURCE]::sb)){
            Write-Error "Unmapped markets cannot be determined from $source"
            return
        }
    }
    if ($condition -eq 'wrong-definition'){
        if ((Test-Path $marketDefinitonsFile)) {
            Write-Host "Mounting '$marketDefinitonsFile'" -NoNewline

            $marketDefinitions = (Get-Content $marketDefinitonsFile | Out-String | ConvertFrom-Json | Select-Object -ExpandProperty definitionMarkets | Sort-Object { [int]$_.id })
            Write-Host " :: OK (total: $($marketDefinitions.Count))"
        }
        else {
            Write-Error "File '$marketDefinitonsFile' doesn't exists"
            return
        }
    }
    #endregion

    #region Init

    $logFile = [Session]::getCurrent().auditLogFile
    $processor = [ProcessorFactory]::getBySource($source)

    $totalLines = $logFile.AssignFile($source)
    $count=0;

    #endregion

    while (-not $logFile.EOF()) {
        $line = $logFile.ReadLine()

        if ($processor.isMarketRelated($line, [SEARCH_SCOPE]::internalId, '*')){
            $processor.ProcessMessage($line)
            $processor.ProcessMarket()

            [Market[]] $allMarkets += $processor.message.event.markets
        }

        $count++
        $percentage = 100 * $count / $totalLines
        Write-Progress -Activity "Read $source content..." -PercentComplete $percentage
    }
    Write-Progress -Activity $progressMessage -Completed

    switch ($condition) {
        'mutable' {
            #Write-Output 'Identifying mutable...'
            $analysis = ($allMarkets | Select-Object id, type, externalId, specifiers -Unique | Sort-Object type | Group-Object type)
            $mutable = ($analysis | Where-Object { -not (($_.group[0].specifiers) -or (-not $_.group[0].specifiers -and $_.count -eq 1)) } )
            $items = $mutable
        }
        'immutable' {
            #Write-Output 'Identifying immutable...'
            $analysis = ($allMarkets | Select-Object id, type, externalId, specifiers -Unique | Sort-Object type | Group-Object type)
            $immutable = ($analysis | Where-Object { ($_.group[0].specifiers) -or (-not $_.group[0].specifiers -and $_.count -eq 1) })
            $items = $immutable
        }
        'mapped'{
            $analysis = ($allMarkets | Select-Object id, type, externalId, specifiers -Unique | Sort-Object id | Group-Object id)
            $mapped = $analysis
            $items = $mapped
        }
        'unmapped'{
            $analysis = ($allMarkets | Select-Object id, type, externalId, specifiers -Unique | Sort-Object id | Group-Object id)
            $mapped = (Find-Markets -source core -condition mapped)

            if ($processor.isTypeBased){
                if ($processor.haveMarketSeparator) {
                    $func = { -not $_.type.Split('_')[1] -in $mapped.extId }
                }
                else {
                    $func = { -not $_.type -in $mapped.extId }
                }
            }
            else {
                if ($processor.haveMarketSeparator) {
                    $func = { -not $_.id.Split('_')[1] -in $mapped.extId }
                }
                else {
                    $func = { -not $_.id -in $mapped.extId }
                }
            }

            $unmapped = ($analysis | Where-Object (&$func) )
            $items = $unmapped
        }
        'wrong-definition'{
            # take all markets+specifier combination to be checked against the definitions
            $analysis = ($allMarkets | Select-Object id, specifiers -Unique | Sort-Object id | Group-Object id)
            # find aout market definitions which relates to the analyzed ones
            $marketDefinitions = $marketDefinitions | Where-Object { $_.id -in $analysis.name} | Sort-Object { [int]$_.id }

            $wrongDefinition = @()
            for($i=0; $i -lt $analysis.Count; $i++){
                $analyzedSpecifiers = @()

                # collect the specifiers from the analyzed market
                if ($null -ne $analysis[$i].group.specifiers) {
                    foreach ($j in (($analysis[$i].group.specifiers) | Get-Member -Type Properties)) {
                        $analyzedSpecifiers += ($j.Name)
                    }
                }

                $uniqueSpecifiers = ($analyzedSpecifiers | Select-Object -Unique)
                Write-Debug "Analyzed specifiers: $uniqueSpecifiers"

                if ($analysis[$i].name -ne $marketDefinitions[$i].id) {
                    Write-Error "Varios id's are compared: $($analysis[$i].name) vs. $($marketDefinitions[$i].id)"
                }

                # find out that each of collected specifiers exists in the definition
                if ($null -ne $marketDefinitions[$i].specifiers -and $uniqueSpecifiers.count -eq $marketDefinitions[$i].specifiers.count){
                    foreach ($k in ($marketDefinitions[$i].specifiers.name)) {
                        if (-not ($k -in $uniqueSpecifiers)) {
                            $wrongDefinition += $analysis[$i]
                            break
                        }
                    }
                }
                else{
                    if ($null -ne $analysis[$i].specifiers){
                        $wrongDefinition += $analysis[$i]
                    }
                }
            }
            $wrongDefinition = $wrongDefinition | Group-Object name
            $items = $wrongDefinition
        }
        'all'{
            $analysis = ($allMarkets | Select-Object * -Unique | Sort-Object id | Group-Object id)
            $items = $analysis
        }
    }
    $total = $analysis.Count

    if ($sortBy -eq 'changes') {
        #Write-Output 'Grouping by frequency...'
        $analysis = ($allMarkets | Select-Object type, id | Sort-Object type | Group-Object type | `
            Select-Object count, name | Where-Object { $_.name -in $items.name})

        switch ($condition) {
            'mutable' {
                #Write-Output 'Grouping mutable markets...'
                $mutable = ($analysis | Where-Object { $_.name -in $mutable.name } | Sort-Object count -Descending)
            }
            'immutable' {
                #Write-Output 'Grouping immutable markets...'
                $immutable = ($analysis | Where-Object { $_.name -in $immutable.name } | Sort-Object count -Descending)
            }
            'mapped' {
                $mapped = ($analysis | Where-Object { $_.name -in $mapped.name } | Sort-Object count -Descending)
            }
            'unmapped' {
                $unmapped = ($analysis | Where-Object { $_.name -in $unmapped.name } | Sort-Object count -Descending)
            }
            'wrong-definition'{
                $wrongDefinition = ($analysis | Where-Object { $_.name -in $wrongDefinition.name } | Sort-Object count -Descending)
            }
            'all' {
                $analysis = ($analysis | Sort-Object count -Descending)
            }
        }
    }

    switch ($condition) {
        'mutable' {
            Write-Output ($mutable | Select-Object count, name)
            Write-Output ''
            if ($mutable.count){
                Write-Output ("From total {0} markets, there are {1} mutable!" -f @($total, $mutable.count)) #-ForegroundColor Red
            }
            else{
                Write-Output "From total $total markets, there are no mutable markets!" #-ForegroundColor Yellow
            }

            break
        }
        'immutable' {
            Write-Output ($immutable | Select-Object count, name)
            Write-Output ''
            if ($immutable.count){
                Write-Output ("From total {0} markets, there are {1} immutable!" -f @($total, $immutable.count)) #-ForegroundColor Green
            }
            else{
                Write-Output "From total $total markets, there are no immutable markets!" #-ForegroundColor Yellow
            }

            break
        }
        'mapped' {
            Write-Output ($mapped | Select-Object count, name)
            Write-Output ''
            if ($mapped.count){
                Write-Output ("From total {0} markets, there are {1} mapped!" -f @($total, $mapped.count)) #-ForegroundColor Green
            }
            else{
                Write-Output "From total $total markets, there are no mapped markets!" #-ForegroundColor Yellow
            }

            break
        }
        'unmapped' {
            Write-Output ($unmapped | Select-Object count, name)
            Write-Output ''
            if ($unmapped.count){
                Write-Output ("From total {0} markets, there are {1} unmapped!" -f @($total, $unmapped.count)) #-ForegroundColor Green
            }
            else{
                Write-Output "From total $total markets, there are no unmapped markets!" #-ForegroundColor Yellow
            }

            break
        }
        'wrong-definition' {
            Write-Output ($wrongDefinition | Select-Object count, name)
            Write-Output ''
            if ($wrongDefinition.count){
                Write-Output ("From total {0} markets, there are {1} with wrong definition!" -f @($total, $wrongDefinition.count)) #-ForegroundColor Green
            }
            else{
                Write-Output "From total $total markets, all have good definition!" #-ForegroundColor Yellow
            }

            break
        }
        'all' {
            Write-Output ($analysis | Select-Object count, name)
            Write-Output ''
            if ($total -gt 0){
                Write-Output "Total $total markets" #-ForegroundColor Green
            }
            else{
                Write-Output "Input doesn't contain any market." #-ForegroundColor Red
            }

            break
        }
    }
}