modules/SessionConfig.psm1

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

class SessionConfig{
    #region Properties

    hidden [string] $dtFileFormat = 'yyyyMMddHHmmss'
    hidden [string] $tsFileFormat = 'hhmmss'
    hidden [string] $uriExternalId = 'https://sports-api.{0}/sportsbook/rest/v2/matches/external/{1}/{2}{3}'

    [OPERATOR] $operator
    [ENVIRONMENT] $environment
    [string] $timezone
    [string] $domain
    [PSCustomObject] $downloader
    [SOURCE[]] $analyzedSources
    hidden [SOURCE[]] $configuredSources

    # Calculated properties
    [string] $logFilePath

    # Analyzed scope
    [QUERY_TYPE] $queryType
    [int] $matchId
    [string] $referentTime
    [string] $timeSpan
    [datetime] $afterDateTime
    [datetime] $beforeDateTime

    #endregion

    #region Constructors

    SessionConfig([OPERATOR] $operator, [ENVIRONMENT] $environment){
        $this.Init($operator, $environment)
    }

    SessionConfig([OPERATOR] $operator, [ENVIRONMENT] $environment, [long] $matchId, [string] $referentTime, [string] $timeSpan){
        $this.Init($operator, $environment)
        $this.setAnalyzedScope($matchId, $referentTime, $environment)
    }

    hidden Init([OPERATOR] $operator, [ENVIRONMENT] $environment){
        # setup current Operator's environment
        $config = [Config]::Load()

        $operatorEndpoint = $config.endpoints.$operator.$environment

        $this.operator = $operator
        $this.environment = $environment
        $this.timezone = $operatorEndpoint.timezone
        $this.domain = $operatorEndpoint.domain
        $this.downloader = [ObjectHelper]::MergeObject($operatorEndpoint.downloader, $config.downloaders[$operatorEndpoint.downloader.type])

        if ($operatorEndpoint.downloader){
            $this.configuredSources = @()
            foreach ($src in $operatorEndpoint.downloader.sources.PSObject.Properties){
                if ($src.Value){ $this.configuredSources += $src.Name }
            }

            $this.logFilePath = '{0}/{1}/{2}' -f @($config.auditLogFolder, $this.operator, $this.environment)
            $this.CreateAuditLogFolders()
        }
    }

    #endregion

    [void] setAnalyzedScope([SOURCE[]] $sources, [long] $matchId, [string] $referentTime, [string] $timeSpan){
        if (-not $sources) { $this.analyzedSources =$this.configuredSources }
        else { $this.analyzedSources = $sources }

        $this.matchId = $matchId
        $this.referentTime = $referentTime
        $this.timeSpan = $timeSpan
        $this.afterDateTime, $this.beforeDateTime = [DateTimeHelper]::getAfterBefore($referentTime, $timeSpan)

        if ($matchId) { $this.queryType = [QUERY_TYPE]::matchId}
        if ($referentTime){ $this.queryType = [QUERY_TYPE]::combined }
        if (-not $matchId){ $this.queryType = [QUERY_TYPE]::datetimeInterval }

        Write-Host ('Analyzed period: {0} - {1} ({2})' -f @($this.afterDateTime, $this.beforeDateTime, `
            [DateTimeHelper]::FormatTimespan($this.beforeDateTime - $this.afterDateTime)))
    }

    hidden [void] CreateAuditLogFolders(){
        if (-not (Test-Path $this.logFilePath)) {
            Write-Host "Creating operator's environment folder..."
            New-Item -Path $this.logFilePath -ItemType "directory" | Out-Null
        }
    }

    hidden [string] getFileName([string] $source, [string]$extension){

        $retValue = ''

        switch ($this.queryType) {
            ([QUERY_TYPE]::matchId) {
                $retValue = ('{0}/{1}-{2}.{3}' -f @($this.logFilePath, $this.matchId, $source, $extension))
            }
            ([QUERY_TYPE]::datetimeInterval) {
                $retValue = ('{0}/{1}_{2}-{3}.{4}' -f @($this.logFilePath,  `
                    $this.afterDateTime.ToString($this.dtFileFormat), $this.beforeDateTime.ToString($this.dtFileFormat), $source, $extension))
            }
            ([QUERY_TYPE]::combined) {
                $retValue = ('{0}/{1}-{2}_{3}-{4}.{5}' -f @($this.logFilePath, $this.matchId,  `
                    $this.afterDateTime.ToString($this.dtFileFormat), $this.beforeDateTime.ToString($this.dtFileFormat), $source, $extension))
            }
        }

        return $retValue
    }

    [string] getFileName([SOURCE] $source, [string]$extension){
        return $this.getFileName([string]$source, $extension)
    }

    [bool] ApproveDownload() {

        $min = $null; $max = $null
        $missingFile = $false

        foreach ($src in $this.analyzedSources){
            $file = $this.getFileName($src, '*')

            if ($global:DEBUG) { Write-Host "Checking file: $file" -ForegroundColor yellow }

            if (Test-Path $file) {
                $fileDate = ((Get-ChildItem $file).LastWriteTime | Sort-Object -Descending)[0]
                if ($global:DEBUG) { Write-Host "File date: $fileDate" -ForegroundColor yellow }

                if (-not $min -or $fileDate -lt $min){
                    $min = $fileDate
                }
                if (-not $max -or $fileDate -gt $max){
                    $max = $fileDate
                }
            }
            else {
                $missingFile = $true
                if ($global:DEBUG) { Write-Host "Missing file!" -ForegroundColor yellow }
                break
            }
        }

        if ($missingFile){
            Write-Host "Logs are not complete, download initialized..."
            return $true
        }

        Write-Host "There are downloaded audit log files from before ($min - $max)"
        $answer = Read-Host -Prompt 'Using already downloaded files? ([y]/n)'

        return ($answer -in ('n', 'no'))
    }

    [string] UriFindExternalId([string] $key, [string]$prefix, [int]$matchId){
        return ($this.uriExternalId -f @($this.domain, $key, $prefix, $matchId))
    }
}