FlexAnalyzer.psm1

#FlexLogAnalyzer Runs analyses against Flex Logs gathered from UC-Engine.
Add-Type -AssemblyName PresentationFramework


[string]$global:FlexLog = ""

#Current Versions
[string]$global:Ccs = "1.00.17.705"
[string]$global:MTR = "4.8.31.0"
[string]$global:OS = "10.0.19042"

[string]$global:Huddly = "1.4.12"
[string]$global:SB1 = "1.001.0098.26"
[string]$global:HdConv = "47"

[string]$global:IntelVideo = "26.20.100.8141"
[string]$global:IntelLan = "12.18.9.8"

[string]$global:Tsw1060Firmware = "3.000.0024"
[string]$global:Tsw1070Firmware = "1.002.0047"
[string]$global:UC1Firmware = "1.4395.00030"
[string]$global:UC2Firmware = "1.0.3.36"

#Files
$global:AllFilesAndFolders

#File lookup
[string]$global:FlexVersionInfoSearchString = '*FlexVersionInfo.json*'
[string]$global:MTRInitLogSearchString = 'SkypeRoom-Init*'
[string]$global:SystemEventLogSearchString = 'System.evtx*'
[string]$global:ApplicationEventLogSearchString = 'Application.evtx*'
[string]$global:MTREventLogSearchString = 'Skype Room System.evtx*'
[string]$global:NetworkEventLogSearchString = "Microsoft-Windows-NetworkProfile_Operational.evtx*"
[string]$global:TimeServiceEventLogSearchString = "Microsoft-Windows-Time-Service_Operational.evtx*"
[string]$global:CallInformationFolderSearchString = "SkypeDownloads"
[string]$global:CSServerLogSearchString = "CSServer*"
[string]$global:UtsEngineLogSearchString = "UtsEngine*"
[string]$global:UtsSlaveMgrLogSearchString = "UtsSlaveMgr*"
[string]$global:AppStatusFileSearchString = "AppStatus.txt*"
[string]$global:CIGTFileSearchString = "*_*.*.*.*_*-*-*_*.log"
[string]$global:CRClientListSearchString = "CRClientList.json*"
[string]$global:CustomUISearchString = "*LocalInfo.vtpage*"
[string]$global:UCPRLogSearchString = "*UCPR.log*"
[string]$global:InstalledProgramsSearchString = "*Windows-InstalledPrograms.txt*"
[string]$global:TeamsLogsLatestSearchString = "logs.txt"
[string]$global:TeamsLogsOldSearchString = "old_logs_*"
[string]$global:GPResultSearchString = "*GPResult.txt*"

#Folder
[string]$global:EventLogPathSearchString = "*EventLog*"
$global:DestinationFolder = ""

#variables
[string]$global:UCEngineTimezone 

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.IO.Compression.FileSystem

function Show-Menu {
    write-host 'Main Menu' -ForegroundColor Yellow
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:SystemEventLogSearchString } | ForEach-Object { $color = "white" }
    write-host ' 1: Windows Updates (All)' -ForegroundColor $color
    write-host ' 2: Windows Updates (Relevant)' -ForegroundColor $color
    write-host ' 3: Reboots / Power cycles / MTR restarts' -ForegroundColor $color
    write-host ' 4: Reboots / Power cycles (no MTR/Nightly reboots)' -ForegroundColor $color
    write-host ' 5: Network disconnects' -ForegroundColor $color
    write-host ' 6: MTR account health changes' -ForegroundColor $color
    write-host ' 7: MTR hardware health changes' -ForegroundColor $color
    write-host ' 8: MTR heartbeat information' -ForegroundColor $color
    write-host ' 9: Application crashes' -ForegroundColor $color
    write-host ' 10: Application installs' -ForegroundColor $color
    write-host ' 11: Events between timestamps -- UNDER CONSTRUCTION' -ForegroundColor $color
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CallInformationFolderSearchString } | ForEach-Object { $color = "white" }
    write-host ' 12: Call Information' -ForegroundColor $color
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CSServerLogSearchString } | ForEach-Object { $color = "white" }
    write-host ' 13: Crestron Remote Connection' -ForegroundColor $color
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:UtsSlaveMgrLogSearchString } | ForEach-Object { $color = "white" }
    write-host ' 14: Crestron XIO Cloud Connection' -ForegroundColor $color
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:UCPRLogSearchString } | ForEach-Object { $color = "white" }
    write-host ' 15: UCPR BYOD triggers' -ForegroundColor $color
    $color = "DarkGray"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:TeamsLogsLatestSearchString } | ForEach-Object { $color = "white" }
    write-host ' 16: Rigel Service Events' -ForegroundColor $color
    Write-Host " q: Press 'q' to quit.`n"
}

function Unzip {
    param([string]$zipfile, [string]$outpath)
    if (Test-Path -Path $zipfile.Replace(".zip", "")) {
        write-host("Skipping extract of {0}, folder already found" -f $zipfile) -ForegroundColor DarkGray
    }
    else {
        write-host("Extracting {0}..." -f $zipfile) -ForegroundColor Gray
        [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
    }
}

function setup {
    write-host "FlexLog: $global:FlexLog" -ForegroundColor DarkGray
    if ($global:FlexLog -ne "") { 
        #file passed through argument
        $FilePath = $global:FlexLog
        $FileName = [System.IO.Path]::GetFileName($global:FlexLog)
        $global:DestinationFolder = $global:FlexLog.Replace(".zip", "")
    }
    else {
        #no file passed through argument
        $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{  
            Filter = 'FlexLogs (*.zip)|*.zip'
            Title  = 'Select the FlexLogs .zip file'
        }
        $FileBrowser.ShowDialog()

        $global:DestinationFolder = $FileBrowser.FileName.Replace(".zip", "")
        $FileName = $FileBrowser.SafeFileName
        $FilePath = $FileBrowser.FileName
    }
    
    if ($FileName -Like "*.zip") {
        Unzip $FilePath $FilePath.Replace(".zip", "")
        
        $flag = $true
        while ($flag) {
            $zipFiles = Get-ChildItem -Path $global:DestinationFolder -Recurse | Where-Object { $_.Name -like "*.zip" }
        
            if ($zipFiles.count -eq 0) {
                $flag = $false
            }
            elseif ($zipFiles.count -gt 0) {
                foreach ($zipFile in $zipFiles) {
                    $newName = $zipFile.FullName.Replace(".zip", "")
                    Unzip $zipFile.FullName $newName
                    Remove-Item $zipFile.FullName
                }
            }
            Clear-Variable zipFiles
        }
    }
    else {
        write-host("Error: The selected file must be a zip file.") -ForegroundColor Red
        pause
        break
    }

    write-host("")
    $global:AllFilesAndFolders = Get-ChildItem -Path $global:DestinationFolder -Recurse
}

function PrintVersionInfoRecursive {
    param($JsonData, $ParentName, $Depth)
    $mainAdapter = $false
    $baseIndent = " "
    $JsonData.psobject.properties | Foreach-object {
        if (($_.value.GetType() -eq [String]) -or ($_.value.GetType() -eq [int])) {
            $additionalMessage = ""
            
            1..$Depth | ForEach-Object { Write-Host -NoNewline ($baseIndent) }
            $color = "DarkGray"
            if ($_.Name -like "*SerialNum*" -or
                $_.Name -like "*RoomName*" -or
                $_.Name -like "*IPAddress*" -or
                $_.Name -like "BIOS*") {
                $color = "white"
            }
            if ($_.Name -like "*SoundBarVer*") {
                if ([System.Version]$_.Value -ge [System.Version]$global:SB1) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*WindowsOS*") {
                if ([System.Version]$_.Value -ge [System.Version]$global:OS) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*IntelVideo*") {
                if ([System.Version]$_.Value -ge [System.Version]$global:IntelVideo) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*IntelLan*") {
                if ([System.Version]$_.Value -ge [System.Version]$global:IntelLan) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*AppVer*") {
                if ([System.Version]$_.Value -ge [System.Version]$global:MTR) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*Sleep*") {
                if ($_.value -eq 0) { $color = "Green" } else { $color = "Red" }
            }
            if ($_.Name -like "*Description*") {
                if ($_.value -like "*Intel*Ethernet*I219*" -or $_.value -like "*Hyper-V Virtual*" -or $_.value -like "*Realtek USB FE Family Controller*") 
                { $color = "Green" } else { $color = "Red"; $additionalMessage = " - Adpater not recognized" }
                if ($_.value -like "*Intel*Ethernet*I219*") { $mainAdapter = $true } else { $mainAdapter = $false }
                if ($_.value -like "*Wireless*") { $additionalMessage = " - Wifi is strongly discouraged for Teams. Often people will use Wifi to have Internet access to gather logs" }
            }
            if ($_.Name -like "*DHCPEnabled*" -and $mainAdapter -eq $true) {
                if ($_.value -like "*True*") { $color = "Green" } else { $color = "Red" }
            }
            if ($ParentName -like "*General*" -and $_.Name -like "Version") {
                if ([System.Version]$_.Value -ge [System.Version]$global:Ccs) { $color = "Green" } else { $color = "Red" }
            }
            if ($ParentName -like "*CameraInfo*" -and $_.Name -like "Version") {
                try {
                    if ([System.Version]$_.Value.Substring(0, $_.Value.IndexOf('-')) -ge [System.Version]$global:Huddly) { $color = "Green" } else { $color = "Red" }
                }
                catch {
                    $color = "white"
                }
            }
            if ($ParentName -like "*ContentIngest*" -and $_.Name -like "FW") {
                if ($_.Value -ge $global:HdConv) { $color = "Green" } else { $color = "Red" }
            }
            
            write-host ("$($_.Name): $($_.value)$($additionalMessage)") -ForegroundColor $color
        }
        elseif ($_.value.GetType() -eq [Object[]]) {
            1..$Depth | ForEach-Object { Write-Host -NoNewline $baseIndent }
            write-host ("$($_.Name):") -ForegroundColor Yellow
            
            $_.value | ForEach-Object { 
                if ($_.GetType() -eq [String] -or $_.GetType() -eq [int]) {
                    1..$Depth + 1 | ForEach-Object { Write-Host -NoNewline $baseIndent }
                    #write-host ("$($_)") -ForegroundColor DarkGray
                    if ($_ -like "*DP monitor*" -or $_ -like "*EDIIG0216*" -or $_ -like "*CrestVirtual*") { $color = "Green" }
                    else { $color = "Red" }
                    write-host ("$($_)") -ForegroundColor $color
                }
                else {
                    $Depth = $Depth + 1
                    PrintVersionInfoRecursive -JsonData $_ -Depth $Depth
                    $Depth = $Depth - 1
                }
            }
        }
        else {
            1..$Depth | ForEach-Object { Write-Host -NoNewline  $baseIndent }
            write-host ("$($_.Name):") -ForegroundColor Yellow
            $Depth = $Depth + 1
            PrintVersionInfoRecursive -JsonData $_.value -ParentName $_.Name -Depth $Depth
            $Depth = $Depth - 1
        } 
    }
}

function Show-FlexVersionInfo {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:FlexVersionInfoSearchString } | ForEach-Object { $FlexVersionInfoFile = $_.FullName }
    if ( $null -eq $FlexVersionInfoFile) {
        write-host("FlexVersionInfo.json file not found") -ForegroundColor Red
    }
    else {
        $FlexVersionInfo = Get-Content -Path $FlexVersionInfoFile | ConvertFrom-Json

        PrintVersionInfoRecursive -JsonData $FlexVersionInfo -Depth 1
    }
}

function Show-MtrSettings {
    $global:AllFilesAndFolders | where-object { $_ -Like $global:MTRInitLogSearchString } | Sort-Object LastWriteTime | Select-Object -Last 1 | ForEach-Object { $LastInitLogFile = $_.FullName } 
    if ($LastInitLogFile -ne "") {
        write-host("")
        write-host("MTR Settings({0})" -f [DateTime](Get-ItemProperty -Path $LastInitLogFile -Name LastWriteTime).lastwritetime) -ForegroundColor Yellow
        Get-Content $LastInitLogFile | Where-Object { $_ -like "*RigelAppSettings*GetSetting*" } | ForEach-Object {
            $_ = $_ -replace '.*Value of ', ''
            if ($_ -like "*ModernAuth*" -or 
                $_ -like "*AudioCaptureCommunicationsDevice*" -or 
                $_ -like "*AudioRenderCommunicationsDevice*" -or 
                $_ -like "*AudioRenderDefaultDevice *" -or 
                $_ -like "*AutoScreenSharing*" -or 
                $_ -like "*BluetoothAdvertisementEnabled*" -or 
                $_ -like "*NoOfFrontOfRoomDisplays*" -or 
                $_ -like "*DisableTeamsAudioSharing*" -or 
                $_ -like "*IsTeamsDefaultClient*") {
                $color = "Cyan"
            }
            else {
                $color = "DarkGray"
            }
            write-host(" {0}" -f $_) -ForegroundColor $color
        }
    }
}

function CheckVarious {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:AppStatusFileSearchString } | ForEach-Object { $AppStatusFile = $_.FullName }
    if ($null -ne $AppStatusFile) {
        write-host ""
        foreach ($line in Get-Content $AppStatusFile) {
            if ($line -like '*Username": *') {
                $user = $line.Split(':')[1]
                if ($user -Like "*Skype*") {
                    write-host " MTR application installed under user $($user)" -ForegroundColor "Green"
                }
                else {
                    write-host " MTR application installed under user $($user)! This can cause various issues most notably with the Custom UI. Advise to uninstall the APP or to re-image the UC-Engine." -ForegroundColor "Red"
                }
            }
        }
    }

    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:GPResultSearchString } | ForEach-Object { $GPResultFile = $_.FullName }
    if ($null -ne $GPResultFile) {
        write-host ""
        foreach ($line in Get-Content $GPResultFile) {
            if ($line -like '*OS Configuration:*') {
                if ($line -like '*Standalone Workstation*') {
                    write-host " System is not domain joined" -ForegroundColor "Green"
                }
                else {
                    <#
                    $result = Read-Host " Open GPResult file? (y/n)"
                    if ($result -eq "y") {
                        Start-Process "$($GPResultFile)"
                    }
                    #>

                    $msgBoxInput = [System.Windows.MessageBox]::Show('System appears to be domain joined. Open GPResult file?', 'Domain joined', 'YesNo', 'Info')
                    switch ($msgBoxInput) {
                        'Yes' { Start-Process "$($GPResultFile)" }
                        'No' { }
                    }
                }
            }
        }
    }
    

    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CustomUISearchString } | ForEach-Object { $CustomUIInfoFile = $_.FullName }
    if ($null -ne $CustomUIInfoFile) {
        write-host ""
        write-host "Custom UI found:" -ForegroundColor Yellow
        foreach ($line in Get-Content $CustomUIInfoFile) {
            if ($line -like '*VTZ=*' -or
                $line -like '*Panel=*' -or
                $line -like '*Date=*' -or
                $line -like '*VTpro-e=*' -or
                $line -like '*Database=*') {
                $user = $line.Split(':')[1]
                
                write-host " $($line)"
                
            }
        }
    }

    write-host ""
    write-host "UC-Engine Time Information:" -ForegroundColor Yellow
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:SystemEventLogSearchString } | ForEach-Object { $SystemEventLogPath = $_.FullName }
    if ($null -ne $SystemEventLogPath) {
        Get-WinEvent -FilterHashtable @{ Path = $SystemEventLogPath; Id = 6013 } | select-object -First 1 | ForEach-Object {
            $timezoneData = ([xml]$_.ToXml()).Event.EventData.Data
            [System.TimeZoneInfo]::GetSystemTimeZones( ) | where-object { $_.StandardName -Like $timezoneData[6].substring($timezoneData[6].indexOf(' ') + 1) } | foreach-object { $timeZone = $_ }
            if ($null -eq $timezone) {
                write-host " TimeZone: $($timezoneData[6])"
            }
            else {
                write-host " TimeZone: $($timeZone)"
                $offset = [string]$timezone.BaseUtcOffset
                $global:UCEngineTimezone = $offset.substring(0, 5)
            }
        }
    }

    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:TimeServiceEventLogSearchString } | ForEach-Object { $TimeServiceEventLogPath = $_.FullName }
    if ($null -ne $TimeServiceEventLogPath) {
        Get-WinEvent -FilterHashtable @{ Path = $TimeServiceEventLogPath; Id = 264 } | select-object -First 1 | ForEach-Object {
            $Message = ([xml]$_.ToXml()).Event.EventData.Data
            write-host " NTP Server: $($_.message.substring(118).split(';')[0].trim())"
        }
    }


    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CIGTFileSearchString } | ForEach-Object { showPanelInfo -LogFile $_.FullName }
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CIGTFileSearchStringMerc } | ForEach-Object { showPanelInfo -LogFile $_.FullName }
} 

function createForm {
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing

    $form = New-Object System.Windows.Forms.Form
    $form.Text = 'Data Entry Form'
    $form.Size = New-Object System.Drawing.Size(300, 200)
    #$form.StartPosition = 'manual'
    $form.Left = 1000
    $form.Top = 0

    $okButton = New-Object System.Windows.Forms.Button
    $okButton.Location = New-Object System.Drawing.Point(75, 120)
    $okButton.Size = New-Object System.Drawing.Size(75, 23)
    $okButton.Text = 'OK'
    $okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
    $form.AcceptButton = $okButton
    $form.Controls.Add($okButton)

    $cancelButton = New-Object System.Windows.Forms.Button
    $cancelButton.Location = New-Object System.Drawing.Point(150, 120)
    $cancelButton.Size = New-Object System.Drawing.Size(75, 23)
    $cancelButton.Text = 'Cancel'
    $cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    $form.CancelButton = $cancelButton
    $form.Controls.Add($cancelButton)

    $label = New-Object System.Windows.Forms.Label
    $label.Location = New-Object System.Drawing.Point(10, 20)
    $label.Size = New-Object System.Drawing.Size(280, 20)
    $label.Text = 'Please enter the information in the space below:'
    $form.Controls.Add($label)

    $textBox = New-Object System.Windows.Forms.TextBox
    $textBox.Location = New-Object System.Drawing.Point(10, 40)
    $textBox.Size = New-Object System.Drawing.Size(260, 20)
    $form.Controls.Add($textBox)

    $form.Topmost = $true

    $form.Add_Shown( { $textBox.Select() })
    $result = $form.ShowDialog()

    if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
        $x = $textBox.Text
        $x
    }
}

function showPanelInfo {
    param($LogFile)
    Write-Host ""
    write-host "Panel logs found:" -ForegroundColor Yellow
    $writeResponse = 0
    $panelModel = ""
    $panelFirmware = ""
    foreach ($line in Get-Content $LogFile) {
        if ($writeResponse -eq 1) {
            if ("*$($global:UCEngineTimezone)*" -Like $line) {
                write-host $line
            }
            else {
                write-host "$($line) - Does not match UC-Engine Timezone: '$($global:UCEngineTimezone)', could cause remote connection issues" -ForegroundColor "Red"
            }
            $writeResponse = 0
        }
        
        if ($line -Like "*ModelName :*") {
            write-host " $($line.trim())" -ForegroundColor "Cyan"
            $panelModel = $line.split(':')[1].Trim()
        }
        if ($line -Like "*IpAddress :*") { write-host " $($line.trim())" }
        if ($line -Like "*Firmware :*") { 
            $panelFirmware = $line.split(':')[1].Trim()
            $color = "Cyan"
            try {
                if ($panelModel -like "*1060*") {
                    if ([System.Version]$panelFirmware -lt [System.Version]$global:Tsw1060Firmware) { $color = "Red" }
                }
                if ($panelModel -like "*1070*") {
                    if ([System.Version]$panelFirmware -lt [System.Version]$global:Tsw1070Firmware) { $color = "Red" }
                }
                if ($panelModel -like "*Merc*") {
                    if ([System.Version]$panelFirmware -lt [System.Version]$global:UC1Firmware) { $color = "Red" }
                }
                if ($panelModel -like "*UC-2*") {
                    if ([System.Version]$panelFirmware -lt [System.Version]$global:UC2) { $color = "Red" }
                }
            }
            catch {
                $color = "Cyan"
            }
            write-host " $($line.trim())" -ForegroundColor $color
        }  
        if ($line -Like "*SerialNumber :*") { write-host " $($line.trim())" }
        if ($line -Like "*MacAddress :*") { write-host " $($line.trim())" }
        if ($line -Like "*Current Time*") { write-host " $($line.trim())" }
        if ($line -Like "Current manifest URL*") { write-host " $($line.trim())" }
        if ($line -Like "timezone") { 
            write-host -NoNewline " TimeZone: " 
            $writeResponse = 1
        }
    }
}


function Show-WindowsUpdates {
    param([string[]]$filters)
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:SystemEventLogSearchString } | ForEach-Object { $SystemEventLogPath = $_.FullName }
    if ($null -ne $SystemEventLogPath) {
        Write-Host ""
        if ($filters.Count -eq 0) {
            write-host("Windows Updates (All)") -ForegroundColor Yellow
        }
        else {
            write-host("Windows Updates (Relevant)") -ForegroundColor Yellow
        }

        Get-WinEvent -FilterHashtable @{ Path = $SystemEventLogPath; ProviderName = '*WindowsUpdateClient' } |
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $xml = ([xml]$_.ToXml()).Event
            $index = [array]::indexOf($xml.EventData.Data.name, 'updateTitle')[0]
            $title = $xml.EventData.Data[$index].'#text'
            switch ($_.Id) {
                19 { $color = 'Green'; $type = "Install success" }
                20 { $color = 'Red'; $type = "Install failed" } 
                43 { $color = 'Gray'; $type = "Install started" }
                44 { $color = 'Gray'; $type = "Download started" } 
    
            }
            if ($filters.Count -eq 0) {
                $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated
                write-host(" {0} `t {1} `t {2}" -f $time, $type, $title) -ForegroundColor $color
            }
            else {
                foreach ($filter in $filters) {
                    $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated
                    if ($title -Like $filter) { write-host(" {0} `t {1} `t {2}" -f $time, $type, $title) -ForegroundColor $color }
                }
            }
        }
    }
}

function Show-restarts {
    param([int]$filter = 0)
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:SystemEventLogSearchString } | ForEach-Object { $SystemEventLogPath = $_.FullName }
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:MTREventLogSearchString } | ForEach-Object { $MTREventLogPath = $_.FullName }
    if ($null -ne $SystemEventLogPath) {
        Write-Host ""
        if ($filter -eq 0) {
            write-host("Reboots / Power cycles / MTR restarts") -ForegroundColor Yellow
        }
        else {
            write-host("Reboots / Power cycles (no MTR/Nightly reboots)") -ForegroundColor Yellow
        }

        $SystemEvents = Get-WinEvent -FilterHashtable @{ Path = $SystemEventLogPath; Id = 41, 1074 } 
        $SrsEvents = Get-WinEvent -FilterHashtable @{ Path = $MTREventLogPath; Id = 4000 } 
        $allEvents = $SystemEvents + $SrsEvents
        $allEvents |
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $Message = ($_.Message -split '\n')[0]
            $EventData = ([xml]$_.ToXml()).Event.EventData.Data 
            switch ($_.Id) {
                41 { $color = 'Red'; $type = "Power cycle, power failure, forced restart or crash" } 
                1074 { 
                    $processEnd = $Message.IndexOf('.')
                    $process = $Message.Substring(12, $processEnd - 8).Trim()
                    $reason = $Message.Substring($Message.IndexOf(":", $Message.IndexOf(".")) + 2).Trim()
                    $type = '{0} ({1})' -f $reason, $process
                    if ($Reason -Like "*Unstable*") { $color = 'red' }
                    elseif ($type -Like '*wmiprvse*') { $color = 'Gray'; $type = "Nightly reboot" }
                    else { $color = 'White' }
                
                }
                4000 { 
                    $EventDataJson = ($EventData | ConvertFrom-Json)
                    $AppVersion = $EventDataJson.("AppVersion")
                    $OSVersion = $EventDataJson.("OSVersion")
                    $IPv4Address = $EventDataJson.("IPv4Address")
                    $color = 'Green'; $type = ("MTR started (App={0}, OS={1})" -f $AppVersion, $OSVersion )
                } 
            }
            if ($filter -eq 1 -and ($type -Match "Nightly reboot" -or $type -Match "MTR started")) { }
            else { 
                $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated
                write-host(" {0} `t {1}" -f $time, $type) -ForegroundColor $color
            }
        }
    }
}

function Show-networkDisconnects {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:NetworkEventLogSearchString } | ForEach-Object { $NetworkEventLogPath = $_.FullName }
    if ($null -ne $NetworkEventLogPath) {
        Write-Host ""
        write-host("Network disconnects") -ForegroundColor Yellow
        Get-WinEvent -FilterHashtable @{ Path = $NetworkEventLogPath; Id = 10001 } | 
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated
            $message = $_.Message.Replace("`n", "").Replace("`r", "").Replace("`t", ", ")
            write-host(" {0} `t {1}" -f $time, $message)
        }
    }
}

function Show-MtrAccountHealth {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:MTREventLogSearchString } | ForEach-Object { $MTREventLogPath = $_.FullName }
    if ($null -ne $MTREventLogPath) {
        Write-Host ""
        write-host("MTR account health changes") -ForegroundColor Yellow

        $PrevStates = @()
        $AllStateChanges = @()
    
        $SrsEvents = Get-WinEvent -FilterHashtable @{ Path = $MTREventLogPath; Id = 2000, 2001 }  
        $SrsEvents |
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            if ($_.Id -eq 2001) {
                $Message = ([xml]$_.ToXml()).Event.EventData.Data
                $Description = ConvertFrom-Json $Message | Select-Object -ExpandProperty "Description"
                $States = $Description.Split(".") | ForEach-Object { $_.Trim() }
                $States = $States | Where-Object { $_ }
            }
            else {
                $states = @('Network status : Healthy', 'Exchange status : Connected', 'Signin status: Healthy', 'Teams Signin status: Healthy')
            }

            for ($i = 0; $i -lt $States.Count; $i++) {
                if ($States[$i] -ne $PrevStates[$i]) {
                    $AllStateChanges += @{"time" = $_.TimeCreated; "state" = $States[$i] }
                }
            }

            $PrevStates = $States
        }
        while ($true) {
            write-host ""
            write-host "Choose status to isolate:"
            write-host(" 1: Network status")
            write-host(" 2: Exchange status")
            write-host(" 3: Signin status")
            write-host(" 4: Teams Signin status")
            write-host(" a: All status changes")
            write-host(" r: Press 'r' to return to main loop")
            $input = Read-Host "Please make a selection"

            $choice = ""
            if ($input -eq "r") { return }
            elseif ($input -eq "") { continue }
            elseif ($input -eq "a") { 
                write-host ""
                write-host("All status changes") -ForegroundColor Yellow
            }
            else {
                switch ($input) {
                    '1' { $choice = "Network status" } 
                    '2' { $choice = "Exchange status" } 
                    '3' { $choice = "Signin status" }  
                    '4' { $choice = "Teams Signin status" } 
                }
                write-host ""
                write-host($choice) -ForegroundColor Yellow
            }
 
            foreach ($stateChange in $AllStateChanges) {
                if ($StateChange.state -like "$choice*") {
                    if ($StateChange.state -like "*UnHealthy*" -or $StateChange.state -like "*Disconnected*" -or $StateChange.state -like "*AutodiscoveryError*") { $color = 'Red' }
                    elseif ($StateChange.state -like "*Healthy*" -or $StateChange.state -like "*Connected*") { $color = 'Green' }
                    else { $color = 'White' }
                    $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $stateChange.time
                    write-host(" {0} `t {1}" -f $time, $stateChange.state ) -ForegroundColor $color
                }
            }
        }
    }
}

function Show-MtrHardwareHealth {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:MTREventLogSearchString } | ForEach-Object { $MTREventLogPath = $_.FullName }
    if ($null -ne $MTREventLogPath) {
        Write-Host ""
        write-host("MTR hardware health changes") -ForegroundColor Yellow

        $PrevStates = @()
        $AllStateChanges = @()
    
        $SrsEvents = Get-WinEvent -FilterHashtable @{ Path = $MTREventLogPath; Id = 3000, 3001 }  
        $SrsEvents |
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $Message = ([xml]$_.ToXml()).Event.EventData.Data
            $Description = ConvertFrom-Json $Message | Select-Object -ExpandProperty "Description"
            $States = $Description.Split(".") | ForEach-Object { $_.Trim() }
            $States = $States | Where-Object { $_ }

            for ($i = 0; $i -lt $States.Count; $i++) {
                if ($States[$i] -ne $PrevStates[$i]) {
                    $AllStateChanges += @{"time" = $_.TimeCreated; "state" = $States[$i] }
                }
        
            }
            $PrevStates = $States
        }
        while ($true) {
            write-host ""
            write-host "Choose status to isolate:" -ForegroundColor Yellow
            $index = 1
            foreach ($State in $PrevStates) {
                write-host(" {0}: {1}" -f $index, $State.Substring(0, $State.IndexOf(':')))
                $index++
            }
            write-host(" a: All status changes")
            write-host(" r: Press 'r' to return to main loop")

            $input = Read-Host "Please make a selection"
            $choice = ""
            if ($input -eq "r") { return }
            elseif ($input -eq "") { continue }
            elseif ($input -eq "a") { 
                write-host ""
                write-host("All status changes") -ForegroundColor Yellow
            }
            else { 
                $choice = $PrevStates[($input -as [int]) - 1].Substring(0, $PrevStates[($input -as [int]) - 1].IndexOf(':')) 
                write-host ""
                write-host($choice) -ForegroundColor Yellow
            }
        
            foreach ($stateChange in $AllStateChanges) {
                if ($StateChange.state -like "$choice*") {
                    if ($StateChange.state -like "*UnHealthy*") { $color = 'Red' }
                    elseif ($StateChange.state -like "*Healthy*") { $color = 'Green' }
                    else { $color = 'White' }
                    $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $stateChange.time
                    write-host(" {0} `t {1}" -f $time, $stateChange.state ) -ForegroundColor $color
                }
            }
        }
    }
}

function Show-MtrHeartbeatInfo {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:MTREventLogSearchString } | ForEach-Object { $MTREventLogPath = $_.FullName }
    if ($null -ne $MTREventLogPath) {
        Write-Host ""
        write-host("MTR heartbeat changes") -ForegroundColor Yellow

        $PrevStates = @()
        $AllStateChanges = @()
    
        $SrsEvents = Get-WinEvent -FilterHashtable @{ Path = $MTREventLogPath; Id = 3000, 3001 }  
        $SrsEvents |
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $Message = ([xml]$_.ToXml()).Event.EventData.Data | ConvertFrom-Json
            $Message.PSObject.Members.Remove("Description")
            $States = @()
            $Message.PSObject.Properties | ForEach-Object {
                #write-host("{0}: {1}" -f $_.Name, $_.Value)
                $States += ("{0}: {1}" -f $_.Name, $_.Value)
            }

            for ($i = 0; $i -lt $States.Count; $i++) {
                if ($States[$i] -ne $PrevStates[$i]) {
                    $AllStateChanges += @{"time" = $_.TimeCreated; "state" = "{0}" -f $States[$i] }
                }
        
            }
            $PrevStates = $States
        }
        while ($true) {
            write-host ""
            write-host "Choose status to isolate:" -ForegroundColor Yellow
            $index = 1
            foreach ($State in $PrevStates) {
                write-host(" {0}: {1}" -f $index, $State.Substring(0, $State.IndexOf(':')))
                $index++
            }
            write-host(" a: All status changes")
            write-host(" r: Press 'r' to return to main loop")

            $input = Read-Host "Please make a selection"
            $choice = ""
            if ($input -eq "r") { return }
            elseif ($input -eq "") { continue }
            elseif ($input -eq "a") { 
                write-host ""
                write-host("All status changes") -ForegroundColor Yellow
            }
            else { 
                $choice = $PrevStates[($input -as [int]) - 1].Substring(0, $PrevStates[($input -as [int]) - 1].IndexOf(':')) 
                write-host ""
                write-host($choice) -ForegroundColor Yellow
            }
        
            foreach ($stateChange in $AllStateChanges) {
                if ($StateChange.state -like "$choice*") {
                    if ($StateChange.state -like "*UnHealthy*") { $color = 'Red' }
                    elseif ($StateChange.state -like "*Healthy*") { $color = 'Green' }
                    else { $color = 'White' }
                    $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $stateChange.time
                    write-host(" {0} `t {1}" -f $time, $stateChange.state) -ForegroundColor $color
                }
            }
        }
    }
}

function Show-AppCrashes {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:ApplicationEventLogSearchString } | ForEach-Object { $ApplicationEventLogPath = $_.FullName }
    if ($null -ne $ApplicationEventLogPath) {
        Write-Host ""
        write-host("Application crashes") -ForegroundColor Yellow
        Get-WinEvent -FilterHashtable @{ Path = $ApplicationEventLogPath; Id = 1000 ; ProviderName = '*Application Error' } | 
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $xml = ([xml]$_.ToXml()).Event
            $title = $xml.EventData.Data[10]
            $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated#.ToUniversalTime()
            if ($title -like '*crestron*') { $color = 'Red' }
            else { $color = 'Gray' }
            write-host(" {0} `t {1}" -f $time, $title) -ForegroundColor $color
        }
    }
}

function Show-AppInstalls {
    Write-Host ""
    write-host("Application Installs") -ForegroundColor Yellow
    Write-Host ""
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:InstalledProgramsSearchString } | ForEach-Object { $InstalledProgramsFilePath = $_.FullName }
    if ($null -ne $InstalledProgramsFilePath) {
        Write-Host(" From InstalledPrograms.txt:") -ForegroundColor Yellow
        $FileText = Get-Content $InstalledProgramsFilePath |  Out-String
        $Json = $FileText | ConvertFrom-Json
        $Json | Sort-Object Publisher | Format-Table | Out-Host
    }
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:ApplicationEventLogSearchString } | ForEach-Object { $ApplicationEventLogPath = $_.FullName }
    if ($null -ne $ApplicationEventLogPath) {
        Write-Host(" From Application Events") -ForegroundColor Yellow
        write-host(" *Warning, this log decays over time or when a Windows feature update occurs, not all installed applications may be listed*") -ForegroundColor Yellow
        Get-WinEvent -FilterHashtable @{ Path = $ApplicationEventLogPath; Id = 1033, 1034 ; ProviderName = '*msiinstaller' } | 
        Sort-Object -Property TimeCreated |
        ForEach-Object {
            $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.TimeCreated
            $message = $_.Message.Replace("`n", "").Replace("`r", "").Replace("`t", ", ")
            switch ($_.Id) {
                1033 { 
                    $message = $message.substring(55)
                    $errorIndex = $message.indexOf("Installation success")
                    $errorcode = $message.substring($errorIndex, $message.length - $errorIndex)
                    $message = $message.substring(0, $errorIndex)
                    if ($message -Like "*Crestron*") { $color = "DarkGray" }
                    else { $color = "White" }
                    write-host(" {0} `t {1}" -f $time, $message) -ForegroundColor $color -NoNewline
                    if ($errorcode -notlike "*: 0.*" ) { $color = "Red" }
                    write-host($errorcode) -ForegroundColor $color
                }
                1034 { write-host(" {0} `t {1}" -f $time, $message) -ForegroundColor "Red" } 
            }
            
        }
    }
}

function Show-EventsBetweenTimestamps {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:EventLogPathSearchString } |  Where-Object { $_.PSIsContainer } | ForEach-Object { $EventLogPath = $_.FullName }
    if ($null -ne $EventLogPath) {
        $EventLogPath
        Write-Host ""
        write-host("Events between timestamps") -ForegroundColor Yellow
        Write-Host ""
        write-host " Enter start time, end time error level(0-5) and detail" -ForegroundColor Yellow
        write-host " Example 1: 2021-03-24 16:12:00 2021-03-24 16:14:00 //Displays everything between timestamps in table view" -ForegroundColor Yellow
        write-host " Example 2: 2021-03-24 16:12:00 2021-03-24 16:14:00 2 d //Displays all error and critical levels between timestamps in detailed view" -ForegroundColor Yellow
        Write-Host ""
        write-host " !!Warning: Event times are always in UTC if your timezone does not match the UC-Engine timezone you need to manually offset the hour!!" -ForegroundColor Red
        write-host " Example: If you are in Belgium +1 and want to review logs from UK +0 you need to add 1 to the hour (10:00 -> 11:00)" -ForegroundColor Yellow
        do {
            Write-Host ""
            Write-Host " return 'r'" -ForegroundColor Yellow
            Write-Host ""
            $response = read-host " Query"
            if ($response -ne 'r') {
                write-host $response
                $response = $response.Split(" ")

                $startTimeString = (($response | Select-Object -Index 0, 1) -join " ").Trim()
                $endTimeString = (($response | Select-Object -Index 2, 3) -join " ").Trim()
        
                $alwaysLog = 1; $critical = 1; $Err = 1; $warning = 1; $info = 1; $verbose = 1;
                $detail = 0

                if ($null -ne $response[4]) {
                    switch ($response[4].Trim()) {
                        '0' { $alwaysLog = 1; $critical = 1; $Err = 1; $warning = 1; $info = 1; $verbose = 1 }
                        '1' { $alwaysLog = 0; $critical = 1; $Err = 0; $warning = 0; $info = 0; $verbose = 0 }
                        '2' { $alwaysLog = 0; $critical = 1; $Err = 1; $warning = 0; $info = 0; $verbose = 0 }
                        '3' { $alwaysLog = 0; $critical = 1; $Err = 1; $warning = 1; $info = 0; $verbose = 0 }
                        '4' { $alwaysLog = 0; $critical = 1; $Err = 1; $warning = 1; $info = 1; $verbose = 0 }
                        '5' { $alwaysLog = 0; $critical = 1; $Err = 1; $warning = 1; $info = 1; $verbose = 1 }
                        'd' { $detail = 1 }
                        Default { $alwaysLog = 1; $critical = 1; $Err = 1; $warning = 1; $info = 1; $verbose = 1 }
                    }
                }
                $startTime = [datetime]::ParseExact($startTimeString, 'yyyy-MM-dd HH:mm:ss', $null)
                $endTime = [datetime]::ParseExact($endTimeString, 'yyyy-MM-dd HH:mm:ss', $null)
                $events = Get-ChildItem -Path $EventLogPath |
                foreach-object { Get-Winevent -FilterHashtable @{ Path = $_.FullName; StartTime = $startTime; EndTime = $endTime } -EA silentlycontinue } |
                where-object {
                    (($_.level -eq 0) -and ($alwaysLog -eq 1)) -or
                    (($_.level -eq 1) -and ($critical -eq 1)) -or
                    (($_.level -eq 2) -and ($Err -eq 1)) -or
                    (($_.level -eq 3) -and ($warning -eq 1)) -or
                    (($_.level -eq 4) -and ($info -eq 1)) -or
                    (($_.level -eq 5) -and ($verbose -eq 1))
                } |
                Sort-Object -Property TimeCreated 
                if ($null -eq $response[5] -and $detail -eq 0) {
                    $events | Format-Table TimeCreated, LogName, ID, Level, ProviderName, Message
                }
                else {
                    $events | Format-List
                }
            }
        }
        until ($response -eq 'r')
    }
}

function Show-CallInformation {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CallInformationFolderSearchString } | ForEach-Object { $SkypeDownloadsFolder = $_.FullName }
    if ($null -ne $SkypeDownloadsFolder) {
        Write-Host ""
        write-host("Call Information") -ForegroundColor Yellow

        if ($SkypeDownloadsFolder -ne "") { $AllCallingFiles = Get-ChildItem -Recurse -Path $SkypeDownloadsFolder | Where-Object { -not $_.PSIsContainer } | where-object { $_ -Like '*calling*' } | Sort-Object firstwritetime } 
        else { Write-Host "Could not find call folder"; return }
        $RecordedCalls = @()

        $counter = 0
        $AllCallingFiles | foreach-object {

            Write-Progress -Activity "Retrieving data from files..." -CurrentOperation $_.FullName -PercentComplete (($counter / $AllCallingFiles.count) * 100)

            $FileText = Get-Content $_.FullName |  Out-String
            $FileText = $FileText.Replace("`n", "").Replace("`r", "").Replace("`t", "")
            $FileText = $FileText -replace '.*Last disposed calls:', ''
            $FileText = $FileText -replace 'Calling Debug data.*', ''

            $Json = $FileText | ConvertFrom-Json
            $Json | ForEach-Object {
            
                $leaveReason = $_.leaveCallContext -replace 'rigel_', ''
                if ($leaveReason -eq "") {
                    $leaveReason = $_.terminatedReason
                }

                $StartTime = [timezone]::CurrentTimeZone.ToLocalTime([DateTime]'1/1/1970').AddMilliseconds($_.extendedCallStateHistory[0].timestamp)
                $EndTime = [timezone]::CurrentTimeZone.ToLocalTime([DateTime]'1/1/1970').AddMilliseconds($_.extendedCallStateHistory[$_.extendedCallStateHistory.Count - 1].timestamp)
                $callDuration = (($_.extendedCallStateHistory[$_.extendedCallStateHistory.Count - 1].timestamp - $_.extendedCallStateHistory[0].timestamp) / 60000)
                if ($callDuration -le 1) {
                    $callDuration = [math]::Round($callDuration * 60)
                    $callDuration = If ($callDuration -lt 2) { "$callDuration second" } Else { "$callDuration seconds" }
                }
                else {
                    $callDuration = [math]::Round($callDuration)
                    $callDuration = If ($callDuration -lt 2) { "$callDuration minute" } Else { "$callDuration minutes" }
                }

                $RecordedCalls += ([pscustomobject]@{StartTime = $StartTime; EndTime = $EndTime; callDuration = $callDuration; leaveReason = $leaveReason }) 
            }
            $counter++
        }

        $faults = 0
        $total = 0

        $RecordedCalls = $RecordedCalls | sort-object -Property StartTime -Unique
        $RecordedCalls | ForEach-Object {
            $total++
            $StartTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.StartTime
            $EndTime = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $_.EndTime
            if ($_.leaveReason -notlike "*console*" -and $_.leaveReason -notlike "*auto_exit*") { $color = "Red"; $faults++ }
            elseif ($_.callDuration -like "*minute*") { $color = "White" }
            else { $color = "DarkGray" }
            write-host(" {0}`t{1}`t{2}`t{3}" -f $StartTime, $EndTime, $_.callDuration, $_.leaveReason) -ForegroundColor $color
        }
        if ($total -eq 0) {
            write-host("")
            write-host(" No call records were found") -ForegroundColor Yellow
        }
        else {
            write-host("")
            write-host(" {0} out of {1} calls ended unexpectedly, {2} percent" -f $faults, $total, [math]::Round($faults / $total * 100)) -ForegroundColor Yellow
        }
    }
}

function Show-RemoteConnections {
    $CSServerLog = $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CSServerLogSearchString } | Sort-Object firstwritetime | Select-Object -ExpandProperty "FullName"
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CRClientListSearchString } | ForEach-Object { $CRClientListFile = $_.FullName }
    
    

    if ($null -ne $CSServerLog) {
        Write-Host ""
        write-host("Crestron Remote Connections") -ForegroundColor Yellow
    
        $colors = @("cyan", "Green", "yellow", "Magenta", "Blue", "DarkCyan", "DarkGreen", "DarkYellow", "DarkMagenta", "DarkBlue")
        $IpAddresses = @()
        $Devices = @()

        if ( $null -ne $CRClientListFile) {
            $CRClientList = Get-Content -Path $CRClientListFile | ConvertFrom-Json
    
            $CRClientList.psobject.properties | Foreach-object {
                $Devices += ($_)
                <#
                write-host ("$($_.Name): $($_.value)")
                $_.value.psobject.properties | Foreach-object {
                    write-host ("$($_.Name): $($_.value)")
                }#>

            }
        }

        foreach ($line in Get-Content $CSServerLog) {
            $appendDeviceInfo = ""
            if ($line -like '*connecting Client *') {
                $line = $line.substring($line.indexOf('.') + 1, $line.length - ($line.indexOf('.') + 1))
                $Ip = $line.substring($line.indexOf("IP=") + 3, $line.length - ($line.indexOf("IP=") + 3))

                $Devices | ForEach-Object {
                    if ($_.Name -like $IP) {
                        $appendDeviceInfo = " - $($_.value.Name), $($_.value.Fw)"
                    }
                }

                if ($line -like '*Disconnecting Client *') {
                    $color = "Red"
                    $line = $line.substring(0, $line.indexOf("Token="))
                }
                else {
                    if ($IpAddresses.Contains($Ip)) {
                        $color = $colors[$IpAddresses.IndexOf($IP) % 10] 
                    }
                    else {
                        $IpAddresses += ($Ip)
                        $color = $colors[$IpAddresses.IndexOf($IP) % 10] 
                    }
                }
                
                #$time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $line.substring(17, $line.length - 17)
                write-host(" {0}{1}" -f $line, $appendDeviceInfo) -ForegroundColor $color
            }
            if ($line -like "*CSServer.log Init*") {
                write-host "---$($line)" -ForegroundColor "White"
            }
        }
    }
}

function Show-XIOCloudConnections {
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:UtsSlaveMgrLogSearchString } | ForEach-Object { $UtsSlaveMgrLog = $_.FullName } | Sort-Object firstwritetime
    if ($null -ne $UtsSlaveMgrLog) {
        Write-Host ""
        write-host("Crestron XIO Cloud Connections") -ForegroundColor Yellow
        <#
        foreach ($line in Get-Content $UtsSlaveMgrLog) {
            if ($line -like '*FCS Json*') {
                $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $line.substring($line.IndexOf("time=") + 5 , ($line.length - $line.indexOf("time=") - 5))
                $json = $line.substring($line.indexOf('{ '), ($line.indexOf(' }') - $line.indexOf(' { ') + 1)) | ConvertFrom-Json
                write-host(" { 0 } `tRegister: { 1 }, { 2 }, { 3 }" -f $time, $json.MACAddress, $json.SerialNumber, $json.Version)
            }
            if ($line -like '* SlaveXiO registration*') {
                $line = $line.substring($line.indexOf('.') + 1, $line.length - ($line.indexOf('.') + 1))
                $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $line.substring($line.IndexOf("time=") + 5 , ($line.length - $line.indexOf("time=") - 5))
                $status = $line.Split(', ')[1].replace(" status = ", "")
                if ($status -like '*Success*') {
                    write-host(" { 0 }`t { 1 }" -f $time, $status) -ForegroundColor Green
                }
                else {
                    write-host(" { 0 }`t { 1 }" -f $time, $status) -ForegroundColor Red
                }
            }
         
            if ($line -like '*Hydrogen Connection Status Changed Reason is*') {
                $line = $line.substring($line.indexOf('.') + 1, $line.length - ($line.indexOf('.') + 1))
                $status = $status = $line.Split(', ')[0].replace(" Hydrogen Connection Status Changed Reason is ", "")
                $time = Get-Date -Format "dd/MM/yyyy HH:mm:ss" $line.substring($line.IndexOf("time=") + 5 , ($line.length - $line.indexOf("time=") - 5))
                if ($status -like '*Connection_Ok*') {
                    write-host(" { 0 }`t { 1 }" -f $time, $status) -ForegroundColor Green
                }
                else {
                    write-host(" { 0 }`t { 1 }" -f $time, $status) -ForegroundColor Red
                }
            }
            }
            #>

        foreach ($line in Get-Content $UtsSlaveMgrLog) {
            if ($line -like '*FCS Json*') {
                Write-Host($line) -ForegroundColor "DarkGray";
            }
            if ($line -like '* SlaveXiO registration*') {
                Write-Host($line) -ForegroundColor "White";
            }
            if ($line -like '*Hydrogen Connection Status Changed Reason is*') {
                Write-Host($line) -ForegroundColor "Yellow"
            }
        }
        
    }
}

function Show-UCPRBYODTriggers {
    $Tab = [char]9
    $global:AllFilesAndFolders | Where-Object { $_ -Like $global:UCPRLogSearchString } | ForEach-Object { $UCPRLog = $_.FullName } | Sort-Object firstwritetime
    if ($null -ne $UCPRLog) {
        Write-Host ""
        write-host("UCPR BYOD Triggers:") -ForegroundColor Yellow
        foreach ($line in Get-Content $UCPRLog) {
            if ($line -like '*OnUCPRDisConnected]R*') {
                $date = ($line.split($Tab)[0].split(' ') | select-object -Index 0, 1) -join " "
                $message = $line.split($Tab)[1]
                Write-Host(" $($date) $($message)") -ForegroundColor "Blue";
            }
            if ($line -like '*OnUCPRConnected*') {
                $date = ($line.split($Tab)[0].split(' ') | select-object -Index 0, 1) -join " "
                $message = $line.split($Tab)[1]
                Write-Host(" $($date) [OnUCPRConnected] UCPR Connected event") -ForegroundColor "Blue";
            }
            if ($line -like '*OnUCPRDigital] Got*') {
                $color = "DarkGray"
                $date = ($line.split($Tab)[0].split(' ') | select-object -Index 0, 1) -join " "
                $message = $line.split($Tab)[1]
                
                if ($line -like '*USB-B*') { $color = "DarkYellow" }
                if ($line -like '*USB-C*') { $color = "Green" }
                if ($line -like '*HDMI*') { $color = "Magenta" }
                Write-Host(" $($date) $($message)") -ForegroundColor $color;
            }
            <#
            if ($line -like '*Sent to Engine*') {
                $date = ($line.split($Tab)[0].split(' ') | select-object -Index 0, 1) -join " "
                $message = $line.split($Tab)[1]
                Write-Host(" $($date) $($message)") -ForegroundColor "White";
            }#>

        }
    }
}

function Show-RigelServiceEvents {
    #$CSServerLog = $global:AllFilesAndFolders | Where-Object { $_ -Like $global:CSServerLogSearchString } | Sort-Object firstwritetime | Select-Object -ExpandProperty "FullName"
    $TeamsLogs = $global:AllFilesAndFolders | Where-Object { $_ -Like $global:TeamsLogsOldSearchString } | Select-Object -ExpandProperty "FullName"
    $TeamsLogs += $global:AllFilesAndFolders | Where-Object { $_ -Like $global:TeamsLogsLatestSearchString } | Select-Object -ExpandProperty "FullName"
    $keyInput = Read-Host "Show initializations?(y/n)"
    $inInitialization = $false
    $color = "DarkGray"
    $prevLine = ""
    if ($null -ne $TeamsLogs) {  
    }
    Write-Host ""
    write-host("Rigel Service Events:") -ForegroundColor Yellow
    foreach ($file in $TeamsLogs) {

        write-host " File: $($file)" -ForegroundColor Yellow
        $newFile = $true
        foreach ($line in Get-Content $file) {
            if ($newFile) {
                if ($prevLine -eq $line -or $prevLine -eq "") {
                    $newFile = $false
                }
                continue
            }
            $prevLine = $line
            if ($line -like '*"type": "INIT",*') {
                $inInitialization = $true
                $color = "DarkGray"
                if ($keyInput -like "y") {
                    write-host " --Initialization start--" -ForegroundColor Yellow
                }
            }
            if ($line -like '*RIGEL-SERVICE:*' -and $line -notlike "*UpdateBluetoothAdvertisementState*" -and $line -notlike "*RigelService::SetTeamsRing*") {
            
                if ($keyInput -like "y") {
                    Write-Host(" $($line)") -ForegroundColor $color
                }
                elseif (-Not ($inInitialization)) {
                    Write-Host(" $($line)") -ForegroundColor $color
                }
            }
            if ($line -like '*"type": "PRUNE_WINDOWS"*') {
                $inInitialization = $false
                $color = "White"
                if ($keyInput -like "y") {
                    write-host " --Initialization end--" -ForegroundColor Yellow
                }
            }
        }
    }
}

function Show-Main {
    Show-Menu
    $keyInput = Read-Host "Please make a selection"
            
    switch ($keyInput) {
        '1' { Show-WindowsUpdates } 
        '2' { Show-WindowsUpdates(@('*crestron*', '*SkypeRoomSystem*', '*Intel - Net*', '*Intel Corporation - Display*', '*feature*', '*Cumulative Update for Windows*')) } 
        '3' { Show-restarts } 
        '4' { Show-restarts(1) }
        '5' { Show-NetworkDisconnects }
        '6' { Show-MtrAccountHealth }
        '7' { Show-MtrHardwareHealth }
        '8' { Show-MtrHeartbeatInfo }
        '9' { Show-AppCrashes }
        '10' { Show-AppInstalls }
        '11' { Show-EventsBetweenTimestamps }
        '12' { Show-CallInformation }
        '13' { Show-RemoteConnections }
        '14' { Show-XIOCloudConnections }
        '15' { Show-UCPRBYODTriggers }
        '16' { Show-RigelServiceEvents }
        'q' { return 'q' }
    }
    Write-Host ""
}

function Start-FlexAnalyzer {
    param([string]$FlexLog)

    $global:FlexLog = $FlexLog

    Write-Host "=================== $MainTitle ===================`n$LogOLH`n"
    setup
    Show-FlexVersionInfo
    Show-MtrSettings
    CheckVarious
    <#createForm#>

    Write-Host ""
    while ($return -ne 'q') {
        $return = Show-Main
    }
}


Export-ModuleMember -Function Start-FlexAnalyzer