modules/FeedProcessor/AuditLog/Market.psm1

using module '..\..\Enums.psm1'
using module '..\..\Helper\ObjectHelper.psm1'
using module '..\..\Helper\DateTimeHelper.psm1'
using module '.\Outcome.psm1'

class Market {
    [string] $id
    [string] $externalId
    [string] $name
    [string] $action
    [string] $status
    [string] $type
    [hashtable] $specifiers
    [string] $resulted

    [Outcome[]] $outcomes
    [hashtable] $other

    [bool] $isForced

    Market() {
        $this.outcomes = @()
        $this.other = @{}
    }

    Market([string] $id, [string] $externalId, [string] $name, [string] $action, [string] $status, `
        [string] $type, [hashtable] $specifiers, [string] $resulted) {

        $this.Market()

        $this.id = $id
        $this.externalId = $externalId
        $this.name = $name
        $this.action = $action
        $this.status = $status
        $this.type = $type
        $this.specifiers = $specifiers
        $this.resulted = $resulted
    }

    [string] ident(){
        return ('{0}#{1}' -f @($this.id, [ObjectHelper]::ConvertToObject($this.specifiers)))
    }

    static [object[]] reverseIdent([string] $ident){
        $temp = $ident.Split('#')
        return $temp[0], [PSCustomObject]$temp[1]
    }

    [Outcome] FindOutcome([string] $id){
        foreach ($o in $this.outcomes) {
            if ($o.id -eq $id){ return $o }
        }

        return $null
    }

    [void] Aggregate([Market] $m){
        if ($null -ne $m) {
            if (-not $this.action) { $this.action = $m.action }
            if (-not $this.status) { $this.status = $m.status }
            if (-not $this.resulted) { $this.resulted = $m.resulted }

            $this.isForced = ($this.outcomes.Count -eq 0)

            $this.other = [ObjectHelper]::MergeHashtables($this.other, $m.other)
            $this.outcomes = [ObjectHelper]::MergeObjectArray($this.outcomes, $m.outcomes, 'id')

            foreach ($outcome in $this.outcomes) {
                if ($this.isForced) { $outcome.status = $m.status }
                $outcome.Aggregate($m.FindOutcome($outcome.id))
            }
        }
    }

    [bool] Equal([Market] $market, [bool] $sameProducer){
        if (-not $market) { return $false }

        $retValue = ([ObjectHelper]::isEqualHashTable($this.specifiers, $market.specifiers) -and `
            ($this.resulted -eq $market.resulted -or ($this.resulted -in ('', 'False') -and $market.resulted -in ('', 'False'))) -and `
            $this.outcomes.Count -eq $market.outcomes.Count)

        if ($retValue){
            if ($sameProducer){
                foreach ($outcome in $this.outcomes) {
                    $retValue = ($this.id -eq $market.id -and $this.status -eq $market.status -and $outcome.Equal($market.FindOutcome($outcome.id)))
                }
            }
            else {
                $retValue = ($this.OutcomesToString() -eq $market.OutcomesToString())
            }
        }

        return $retValue
    }

    # check with DFS team about mixng Suspended and Stopped
    [string] OutcomesToString(){
        [string[]] $retValue = $null

        foreach ($outcome in ($this.outcomes | Sort-Object {[int] $_.price})) {
            $retValue += $outcome.ToString()
        }

        if ($retValue){
            return [string]::Join(', ', $retValue)
        }
        else {
            return ''
        }
    }

    [Market] Copy(){
        $market = [Market]::new()

        $market.id = $this.id
        $market.externalId = $this.externalId
        $market.name = $this.name
        $market.action = $this.action
        $market.status = $this.status
        $market.type = $this.type
        $market.specifiers = $this.specifiers
        $market.resulted = $this.resulted

        foreach ($o in $this.outcomes) {
            $market.outcomes += $o.Copy()
        }

        $market.other = $this.other

        return $market
    }

    [PSCustomObject] displayInfo(){
        $info = @{}
        if ($this.externalId) { $info.Add('external', $this.externalId) }
        if ($this.type) { $info.Add('type', $this.type) }
        if ($this.resulted) { $info.Add('resulted', $this.resulted) }

        return ([ObjectHelper]::ConvertToObject($info))
    }

    [PSCustomObject] displayOrigin([PSCustomObject] $messageOther){
        return ([ObjectHelper]::ConvertToObject($this.other + $messageOther))
    }
}