lib/functions/functions.ps1

#######################################################################################################################################################
# WARNING: DO NOT EDIT THIS FILE AS IT IS GENERATED AND WILL BE OVERWRITTEN ON THE NEXT UPDATE! #
# #
# Generated via psake on: 2025-01-06T14:06:20.351Z #
# Version: 2025.1.6.8 #
# Copyright Fortigi (C) 2025 #
#######################################################################################################################################################



function Clear-Variables {
    try {

        $EndVariables = Get-Variable
        $SkipVariableNames = @("WshShell", "WhatIfPreference", "WarningPreference", "VerbosePreference", "true", "PSItem", "Task")
        foreach ($EndVariable in $EndVariables) {
            if ($EndVariable.Name -notin $StartVariables.Name -and $EndVariable.Name -notin $SkipVariableNames) {
                try {
                    Remove-Variable -Name $EndVariable.Name -Force -ErrorAction SilentlyContinue
                }
                catch {}
            }
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Close-SplashScreenForm {
    try {

        "Closing Splash Screen" | Write-LogOutput -LogType DEBUG
        try {
            $SplashScreenForm.Hide()
            $SplashScreenForm.Dispose()
        }
        catch {}

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-AllControls {
    param (
        [System.Windows.DependencyObject]$Parent
    )

    try {

        $Controls = @()
        if ($Parent -is [System.Windows.Controls.Control]) {
            $Controls += $Parent
        }

        for ($i = 0; $i -lt [System.Windows.Media.VisualTreeHelper]::GetChildrenCount($Parent); $i++) {
            $Child = [System.Windows.Media.VisualTreeHelper]::GetChild($Parent, $i)
            $Controls += Get-AllControls -Parent $Child
        }

        return $Controls

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Get-Icon {
    PARAM(
        [ValidateSet("Wpf", "WinForms", "Base64")]
        [string]$Type = "WinForms"
    )

    try {

        $Base64Icon = "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"

        $IconBytes = [System.Convert]::FromBase64String($Base64Icon)

        $MemoryStream = New-Object System.IO.MemoryStream(, $IconBytes)

        switch ($Type) {
            "Wpf" {
                $Icon = New-Object System.Windows.Media.Imaging.BitmapImage
                $Icon.BeginInit()
                $Icon.StreamSource = $MemoryStream
                $Icon.CacheOption = [System.Windows.Media.Imaging.BitmapCacheOption]::OnLoad
                $Icon.EndInit()
                $Icon.Freeze()  # Freeze to make it thread-safe

                return $Icon
            }
            "WinForms" {
                return [System.Drawing.Icon]::new($MemoryStream)
            }
            Default {
                return $Base64Icon
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-OmadaGetPagingDataObject {
    PARAM(
        [parameter(Mandatory = $True, Position = 0)]
        [string]$DataType,
        [parameter(Mandatory = $True, Position = 1)]
        [hashtable]$DataTypeArgs,
        [parameter(Mandatory = $False, Position = 3)]
        [string]$SearchString = $null,
        [parameter(Mandatory = $false, Position = 4)]
        [int]$Rows = 1000
    )

    try {

        $Script:RunTimeData.RestMethodParam.Body = [ordered]@{
            _search      = $false
            nd           = 1732546553116
            rows         = $Rows
            page         = 1
            sidx         = [string]::IsNullOrWhiteSpace($SearchString) ? $null : "name"
            sord         = "asc"
            searchField  = $null
            searchString = [string]::IsNullOrWhiteSpace($SearchString) ? $null : $SearchString
            searchOper   = $null
            filters      = $null
            dataType     = $DataType
            dataTypeArgs = $DataTypeArgs
        }

        $Script:RunTimeData.RestMethodParam.Uri = '{0}/WebService/JQGridPopulationWebService.asmx/GetPagingData' -f $Script:AppConfig.BaseUrl
        $Script:RunTimeData.RestMethodParam.Method = "POST"

        return Invoke-OmadaPSWebRequestWrapper

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-SqlQueryObject {
    try {
        if(!(Test-ConnectionRequirements)){
            "Connection not ready" | Write-LogOutput -LogType DEBUG
            return
        }
        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentSqlQuery.DoId)) {
            $Script:MainWindowForm.Elements.TextBoxURL.Text.Trim() | Invoke-ConfigSetting -Property "BaseUrl"

            "Retrieve current query for SqlQuery DoId: {0}" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput -LogType DEBUG
            $Script:RunTimeData.RestMethodParam.Uri = "{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING({1})" -f $Script:AppConfig.BaseUrl, $Script:AppConfig.CurrentSqlQuery.DoId
            "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG

            "Retrieve query {0}" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput

            $Script:RunTimeData.RestMethodParam.Body = $Null
            $Script:RunTimeData.RestMethodParam.Method = "GET"
            try {
                return Invoke-OmadaPSWebRequestWrapper
            }
            catch {
                if ($_.Exception.StatusCode -eq 404) {
                    "Query {0} not found! Clearing current value." -f $Script:AppConfig.CurrentSqlQuery.FullName | Write-LogOutput -LogType WARNING
                    $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $Null
                    return $null
                }
                else {
                    $_.Exception.Message | Write-LogOutput -LogType ERROR
                }
            }

            "Retrieved object {0}" -f $Script:RunTimeData.SqlQueryObject | Write-LogOutput -LogType VERBOSE
        }
        else {
            "CurrentSqlQuery DoId is not set! Cannot retrieve Sql query!" | Write-LogOutput -LogType WARNING
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-SqlSchemaObject {
    try {

        if(!(Test-ConnectionRequirements)){
            "Connection not ready" | Write-LogOutput -LogType DEBUG
            return
        }

        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentDataConnection.DoId)) {
            "Retrieve current SqlSchema for data connection DoId: {0}" -f $Script:AppConfig.CurrentDataConnection.DoId | Write-LogOutput -LogType DEBUG
            $Script:RunTimeData.RestMethodParam.Uri = "{0}/webservice/SyntaxHighlighting.asmx/GetSqlSchema" -f $Script:AppConfig.BaseUrl
            "SqlSchemaUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG

            "Retrieve schema {0}" -f $Script:AppConfig.CurrentDataConnection.FullName | Write-LogOutput

            $Script:RunTimeData.RestMethodParam.Body = @{
                connectionId = $Script:AppConfig.CurrentDataConnection.DoId
            }
            $Script:RunTimeData.RestMethodParam.Method = "POST"
            $ReturnValue = Invoke-OmadaPSWebRequestWrapper

            $Script:SqlSchemaWindowForm.Definition.Title = "Sql Schema - {0}" -f $Script:AppConfig.CurrentDataConnection.FullName

            "Retrieved object {0}" -f $Script:RunTimeData.SqlQueryObject | Write-LogOutput -LogType VERBOSE

            $SchemaObjects = @{}
            $Script:TreeViewSqlSchema.Items.Clear()
            $Schemas = (($ReturnValue.d | Get-Member -MemberType NoteProperty).Name) | ForEach-Object { $_.Split(".")[0] } | Select-Object -Unique
            foreach ($Schema in $Schemas) {
                $Tables = $ReturnValue.d | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -like ("{0}.*" -f $Schema) }

                $TreeViewSchemaItem = New-Object System.Windows.Controls.TreeViewItem
                $TreeViewSchemaItem.Header = $Schema
                $TreeViewSchemaItem.FontSize = 14
                $TreeViewSchemaItem.IsExpanded = $true
                $Script:TreeViewSqlSchema.Items.Add($TreeViewSchemaItem) | Out-Null

                $TableObjects = @{}

                foreach ($Table in $Tables) {

                    $TableFullName = $Table.Name
                    $TableName = $TableFullName.Split(".")[1]

                    $TreeViewTableItem = New-Object System.Windows.Controls.TreeViewItem
                    $TreeViewTableItem.Header = $TableName
                    $TreeViewTableItem.FontSize = 14
                    $TreeViewSchemaItem.Items.Add($TreeViewTableItem) | Out-Null

                    $TableObjects.Add($TableName,($ReturnValue.d.$TableFullName | ForEach-Object { $_.Split(" ")[0] }))


                    foreach ($Column in $ReturnValue.d.$TableFullName) {
                        $TreeViewColumnItem = New-Object System.Windows.Controls.TreeViewItem
                        $TreeViewColumnItem.Header = $Column
                        $TreeViewColumnItem.FontSize = 12
                        $TreeViewColumnItem.Font
                        $TreeViewTableItem.Items.Add($TreeViewColumnItem) | Out-Null
                    }
                }
                $SchemaObjects.Add($Schema,$TableObjects)
            }

            $SchemaObjectsJson = $SchemaObjects | ConvertTo-Json -Depth 5

            "Schema for Monaco editor: {0}" -f $SchemaObjectsJson | Write-LogOutput -LogType VERBOSE
            $OnCompletedScriptBlock = {
                try {
                    if (!$Script:Task.Status -eq "RanToCompletion") {
                        "Monaco Editor Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                    }
                    else{
                        "Monaco Editor Task completed successfully." | Write-LogOutput -LogType DEBUG
                    }
                }
                catch {
                    $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
                }
            }

            "Push schema to Monaco editor." | Write-LogOutput -LogType DEBUG
            Invoke-ExecuteScriptAsync -ScriptToExecute "setSchema($SchemaObjectsJson);" -OnCompletedScriptBlock $OnCompletedScriptBlock

        }
        else {
            "SqlSchema DoID is not set! Cannot retrieve Sql schema!" | Write-LogOutput -LogType WARNING
            return $null
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-SqlTroubleShooterView {

    try {

        $ViewResult = Get-OmadaGetPagingDataObject -SearchString "SQL Troubleshooting" -DataType "Views" -DataTypeArgs @{OwnerShipType = "Both" }
        $View = $null
        if ($null -ne $ViewResult -and $ViewResult.d.Records -gt 0) {
            $View = $ViewResult.d.Rows | Where-Object { $_.Name -eq "SQL Troubleshooting" }
        }
        $Private:Result = $null
        if ($null -ne $View) {
            $DataTypeArgs = [ordered]@{
                viewId          = ("{0}" -f $View.Id)
                pageQueryString = ("{0}/dataobjlst.aspx?view={1}" -f $Script:AppConfig.BaseUrl, $View.Id)
                readOnlyMode    = $false
                countRows       = $false
            }

            $Private:Result = Get-OmadaGetPagingDataObject -DataType "DataObjects" -DataTypeArgs $DataTypeArgs
            $Private:Result = $Private:Result.d.Rows
        }
        return $Private:Result

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-TreeViewItemLevel {
    param (
        [System.Windows.Controls.TreeViewItem]$TreeViewItem
    )
    try {
        $Level = 0
        $Parent = $TreeViewItem.Parent

        while ($null -eq $Parent) {
            if ($Parent -is [System.Windows.Controls.TreeViewItem]) {
                $Level++
            }
            $Parent = $Parent.Parent
        }

        return $Level
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}

function Get-ValidWindowMeasurement {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [parameter(Mandatory = $true)]
        [string]$Setting
    )

    try {
        if ($Setting -in "Width", "Height") {

            $SettingString = "Min{0}" -f $Setting
            if ($Form.$Setting -lt $Form.$SettingString -and $Form.$Setting -gt 0) {
                return [Int]$Form.$SettingString
            }
            else {
                return [Int]$Form.$Setting
            }
        }


    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Get-ValidWindowPosition {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [parameter(Mandatory = $true)]
        [string]$Setting
    )
    try {
        $ActionId = [guid]::NewGuid().ToString()
        if ($Setting -in "Left", "Top") {
            "{0} setting {1}: {2} (Id:{3})" -f $Form.Name, $Setting, $Form.$Setting, $ActionId | Write-LogOutput -LogType VERBOSE2
            if ($Setting -eq "Left") {
                $PrimaryScreenSetting = [system.windows.systemparameters]::PrimaryScreenWidth
                "PrimaryScreenSetting PrimaryScreenWidth {0}: {1} (Id:{2})" -f $Setting, $PrimaryScreenSetting, $ActionId | Write-LogOutput -LogType VERBOSE2
            }
            elseif ($Setting -eq "Top") {
                $PrimaryScreenSetting = [system.windows.systemparameters]::PrimaryScreenHeight
                "PrimaryScreenSetting PrimaryScreenHeight {0}: {1} (Id:{2})" -f $Setting, $PrimaryScreenSetting, $ActionId | Write-LogOutput -LogType VERBOSE2
            }

            if ($Form.$Setting -gt $PrimaryScreenSetting -or $Form.$Setting -lt 0) {
                $Form.$Setting = ($PrimaryScreenSetting - $Form.$Setting) / 2
                "{0} position from screen height '{1}x{2}'. Setting: '{3}' (Id:{4})" -f $Form.Name, $Form.Left, $Form.Top, $Setting, $ActionId | Write-LogOutput -LogType VERBOSE2
                return [Int]::Abs($Form.$Setting)
            }
            else {
                "{0} setting '{1}' (Id:{2})" -f $Form.Name, $Form.$Setting, $ActionId | Write-LogOutput -LogType VERBOSE2
                return [Int]::Abs($Form.$Setting)
            }
        }
        else {
            "{0} setting '{1}' is not valid. (Id:{2})" -f $Form.Name, $Form.$Setting, $ActionId | Write-LogOutput -LogType VERBOSE2
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-WindowPosition {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [switch]$AsString
    )

    try {
        if ($AsString) {
            return "{0}x{1}" -f $Form.Left, $Form.Top
        }
        else {
            return [PSCustomObject]@{
                Left = $Form.Left
                Top  = $Form.Top
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-WindowPositionConfig {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form
    )
    try {
        $Property = "{0}Position" -f $Form.Name
        if ($null -ne $Script:AppConfig.$Property -and $Script:AppConfig.$Property -match "\b\d+x\d+\b") {
            return $Script:AppConfig.$Property
        }
        else {
            return $null
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-WindowSize {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [switch]$AsString
    )
    try {
        "{0}: {1}x{2} AsString: {3}" -f $Form.Name, $Form.Width , $Form.Height, $AsString.IsPresent | Write-LogOutput -LogType VERBOSE2
        if ($AsString) {
            return "{0}x{1}" -f $Form.Width, $Form.Height
        }
        else {
            return [PSCustomObject]@{
                Width  = $Form.Width
                Height = $Form.Height
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Get-WindowSizeConfig {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form
    )
    try {
        $Property = "{0}Size" -f $Form.Name
        if ($null -ne $Script:AppConfig.$Property -and $Script:AppConfig.$Property -match "\d+x\d+") {
            return $Script:AppConfig.$Property
        }
        else {
            return $null
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Initialize-ConfigSettings {
    try {

        Invoke-ConfigSetting -Reset:$Reset.IsPresent

        if ($Script:RunTimeConfig.LogToConsole -or $Script:AppConfig.CheckboxConsoleLog) {
            $Script:RunTimeConfig.LogToConsole = $true
            "Console logging is enabled" | Write-LogOutput -LogType LOG
        }

        if ($null -eq ($Script:MainWindowForm.Definition | Get-WindowPositionConfig)) {
            $Script:MainWindowForm.Definition.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen
        }

        "Pre-set Main Window Components from config" | Write-LogOutput -LogType DEBUG
        $Script:CurrentUrl = $Null
        $Script:MainWindowForm.Elements.TextBoxURL.Text = $Script:AppConfig.BaseUrl
        $Script:MainWindowForm.Elements.TextBoxURL.IsEnabled = $True
        if (![String]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxURL.Text)) {
            $Script:CurrentUrl = $Script:MainWindowForm.Elements.TextBoxURL.Text
            "Config: Current Url: {0}" -f $Script:CurrentUrl | Write-LogOutput -LogType DEBUG
        }

        if ($Script:AppConfig.MyQueriesOnly) {
            "Config: MyQueriesOnly: True" | Write-LogOutput -LogType DEBUG
            $Script:MainWindowForm.Elements.CheckboxMyQueries.IsChecked = $True
        }

        if ($null -ne $Script:RunTimeConfig.Logging.LogLevelSetting) {
            $Script:RunTimeConfig.Logging.LogLevelSetting | Invoke-ConfigSetting -Property "LogLevel"
            "Config: LogLevelSetting: {0}" -f $Script:RunTimeConfig.Logging.LogLevelSetting | Write-LogOutput -LogType DEBUG
        }

        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentSqlQuery.DoId)) {
            "Config: CurrentSqlQuery.DoId: {0}" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput -LogType DEBUG

            $ComboBoxSelectQueryItem = $null
            $ComboBoxSelectQueryItem = $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items | Where-Object { $_.Content -eq $Script:AppConfig.CurrentSqlQuery.FullName }
            if ($null -eq $ComboBoxSelectQueryItem) {
                "Config: Set CurrentSqlQuery.DoId: {0}" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput -LogType DEBUG
                $ComboBoxSelectQueryItem = New-Object System.Windows.Controls.ComboBoxItem
                $ComboBoxSelectQueryItem.Content = $Script:AppConfig.CurrentSqlQuery.FullName
                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Add($ComboBoxSelectQueryItem) | Out-Null
                $Script:RunTimeData.CurrentSqlQuery.DisplayName = $Script:AppConfig.CurrentSqlQuery.DisplayName
                $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $Script:RunTimeData.CurrentSqlQuery.DisplayName
            }
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedValue = $ComboBoxSelectQueryItem
        }

        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentDataConnection.FullName)) {
            "Config: CurrentDataConnection: {0}" -f $Script:AppConfig.CurrentDataConnection.FullName | Write-LogOutput -LogType DEBUG
            Set-DataConnection
        }

        if ([string]::IsNullOrWhiteSpace($Script:AppConfig.LastAuthentication)) {
            "Config: LastAuthentication: {0}" -f $Script:AppConfig.LastAuthentication | Write-LogOutput -LogType DEBUG
            $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedValue = $Script:AppConfig.LastAuthentication
        }

        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.UserName)) {
            "Config: UserName: {0}" -f $Script:AppConfig.UserName | Write-LogOutput -LogType DEBUG
            $Script:MainWindowForm.Elements.TextBoxUserName.Text = $Script:AppConfig.UserName
        }
        Set-OmadaUrl
        Set-AuthenticationOption
        Test-ConnectionSettings

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Initialize-OmadaSqlTroubleShooter {

    try {
        "Initializing application..." | Write-LogOutput -LogType DEBUG

        Push-Location $Script:RunTimeConfig.ModuleFolder

        $Script:RunTimeConfig.Logging.AppLogObject.Add("Application log initialized`r`n")
        $Script:RunTimeConfig.ConfigFile.Name = $Script:RunTimeConfig.ScriptName -replace ".ps1", ".json"
        If (Test-Path $Script:RunTimeConfig.AppDataFolder -PathType Container) {
            New-Item (Join-Path $Script:RunTimeConfig.AppDataFolder -ChildPath "config") -ItemType Directory -Force | Out-Null
            $Script:RunTimeConfig.ConfigFile.Path = (Join-Path $($Script:RunTimeConfig.AppDataFolder) -ChildPath "config\$($Script:RunTimeConfig.ConfigFile.Name)")
        }
        else {
            $Script:RunTimeConfig.ConfigFile.Path = Join-Path $($Script:RunTimeConfig.ModuleFolder) -ChildPath $($Script:RunTimeConfig.ConfigFile.Name)
        }


        try {
            Remove-Variable "Task" -ErrorAction SilentlyContinue
        }
        catch { $Error.Clear() }

        "Load module OmadaWeb.PS" | Write-LogOutput -LogType DEBUG
        Import-Module OmadaWeb.PS

        "Load Assemblies" | Write-LogOutput -LogType DEBUG
        $Env:Path += ";$($Script:RunTimeConfig.ModuleFolder)\Bin"
        $Env:Path += ";$($Script:RunTimeConfig.ModuleFolder)\Bin\Webview2Dlls"
        $Env:Path += ";$($Script:RunTimeConfig.ModuleFolder)"

("System.Windows.Forms", "System.Drawing", "PresentationFramework", "WindowsBase", "PresentationCore", "PresentationFramework") | ForEach-Object {
            "Load assembly: '{0}'" -f $_ | Write-LogOutput -LogType DEBUG
            Add-Type -AssemblyName $_
        }

        "Microsoft.Web.WebView2.Core.dll", "Microsoft.Web.WebView2.Wpf.dll" | ForEach-Object {
            "Load assembly: '{0}'" -f $_ | Write-LogOutput -LogType DEBUG
            $WebViewDllPath = Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "Bin\WebView2Dlls\$_"
            if ((Test-Path $WebViewDllPath -PathType Leaf)) {
                [System.Reflection.Assembly]::LoadFrom($WebViewDllPath) | Out-Null
            }
            else {
                Throw ("The WebView2 Dll '{0}' is cannot be found at the '{1}' bin folder!" -f $_, $DllSource)
                Break
            }
        }
        $WebViewLoaderPath = Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "Bin\WebView2Dlls\WebView2Loader.dll"
        "Get 'WebView2Loader.Dll'" | Write-LogOutput -LogType DEBUG
        if (!(Test-Path $WebViewLoaderPath -PathType Leaf)) {
            Throw ("The WebView2Loader Dll '{0}' is cannot be found at the '{1}' bin folder!" -f "WebView2Loader.dll", $DllSource)
            Break
        }

        $Script:AppConfig = $null
        $Script:RunTimeData = [PSCustomObject]@{
            RestMethodParam                = @{
                Uri                = $Null
                Method             = "GET"
                AuthenticationType = $($Script:AppConfig.LastAuthentication)
            }
            QuerySaved                     = $false
            Password                       = $Null
            QueryText                      = $null
            SqlQueryObject                 = $null
            QueryResult                    = $null
            CurrentQueryText               = $null
            CurrentSqlQuery                = [PSCustomObject]@{
                DoId        = $null
                DisplayName = $null
                FullName    = $null
            }
            StopWatch                      = $null
            QueryListCache                 = @{
                QueryList   = $null
                LastRefresh = Get-Date
                TTL         = 300
            }
            DataobjdlgAspxAttributeMapping = [PSCustomObject]@{
                SqlQueryDoId      = "c-13"
                SqlQueryCreatedBy = "c-2"
                SqlQueryChangedBy = "c-4"
            }
        }
        $Script:WebView = @{
            Object                  = $null
            Environment             = $null
            EdgeWebview2RuntimePath = $null
            UserDataFolder          = $null
        }

        [Windows.Forms.Application]::EnableVisualStyles()

    }
    catch {
        Throw $_
    }
}
function Invoke-ConfigSetting {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'CurrentPoperties', Justification = 'The CurrentPoperties variable is used in a function called from here')]
    PARAM(
        [parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $true)]
        $Value,
        [parameter(Mandatory = $false)]
        [string]$Property,
        [string]$JoinString = " - ",
        [switch]$Reset
    )

    begin {
        try {
            $InputObject = @()
            if ($Reset) {
                "Reset configuration!" | Write-LogOutput -LogType DEBUG
                if (Test-Path ($Script:RunTimeConfig.ConfigFile.Path) -PathType Leaf) {
                    Get-Item ($Script:RunTimeConfig.ConfigFile.Path) | Remove-Item -Force
                }
                $Script:AppConfig = $Null
            }

            if ($null -eq $Script:ConfigProperties) {
                "Read schema!" | Write-LogOutput -LogType DEBUG
                $Script:ConfigProperties = Get-Content (Join-Path (Split-Path (Get-Item $PSScriptRoot).Parent.FullName) -ChildPath "lib\schema\appConfigSchema.json") | ConvertFrom-Json
            }

            if ($Null -ne $Script:AppConfig) {
                $Config = $Script:AppConfig | ConvertTo-Json | ConvertFrom-Json

                $Config | Get-Member -MemberType NoteProperty | ForEach-Object {
                    if ($Script:ConfigProperties.Name -notcontains $_.Name) {
                        "Remove obsolete property {0} from config object!" -f $_.Name | Write-LogOutput -LogType VERBOSE
                        $Config.PSObject.Properties.Remove($_.Name)
                    }
                }

                $CurrentPoperties = $Config | Get-Member -MemberType NoteProperty
                $Script:ConfigProperties | ForEach-Object {
                    Set-ConfigProperty
                }
                "Update config object!" | Write-LogOutput -LogType VERBOSE
            }
            else {
                if (Test-Path ($Script:RunTimeConfig.ConfigFile.Path) -PathType Leaf) {
                    "Read config settings {0}!" -f ($Script:RunTimeConfig.ConfigFile.Path) | Write-LogOutput -LogType VERBOSE
                    $Config = Get-Content ($Script:RunTimeConfig.ConfigFile.Path) | ConvertFrom-Json
                    $CurrentPoperties = $Config | Get-Member -MemberType NoteProperty
                    $Script:ConfigProperties | ForEach-Object {
                        Set-ConfigProperty
                    }
                }
                else {
                    "Create new config object!" | Write-LogOutput -LogType DEBUG
                    $Config = [pscustomobject]@{}
                    $Script:ConfigProperties | ForEach-Object {
                        Set-ConfigProperty
                    }
                }
            }
        }
        catch {
            $_.Exception.Message | Write-LogOutput -LogType ERROR
        }
    }
    process {
        $InputObject += $Value
        $Value = $Value
    }
    end {
        try {
            if (![string]::IsNullOrWhiteSpace($Property)) {
                "Set value for property {0} in config object!" -f $Property | Write-LogOutput -LogType VERBOSE

                $PropertyDefinition = $Script:ConfigProperties | Where-Object { $_.Name -eq $Property }

                switch ($PropertyDefinition.Type) {
                    "String" {
                        $Config.$Property = $Value
                    }
                    "Int" {
                        $Config.$Property = [int]$Value
                    }
                    "Bool" {

                        $Config.$Property = [bool]$Value
                    }
                    "PSObject" {
                        if ($InputObject.Count -eq 1) {
                            $InputString = $InputObject[0].ToString()
                            $LastIndex = $InputString.LastIndexOf($JoinString)

                            if ($LastIndex -le -1) {
                                $Config.$Property = [pscustomobject]@{
                                    DoId        = $InputString
                                    DisplayName = $null
                                    FullName    = $null
                                }
                            }
                            else {
                                $Config.$Property = [pscustomobject]@{
                                    DoId        = [int]$InputString.Substring($LastIndex + ($JoinString.Length - 1)).Trim()
                                    DisplayName = $InputString.Substring(0, $LastIndex).Trim()
                                    FullName    = $null
                                }
                            }
                        }
                        else {
                            $Config.$Property = [pscustomobject]@{
                                DoId        = [int]$InputObject[0]
                                DisplayName = $InputObject[1]
                                FullName    = $null
                            }
                        }
                        $Config.$Property.FullName = $Config.$Property.DisplayName, $Config.$Property.DoId -join " - "
                    }
                }
            }
            "Store config object to {0}. Contents`r`n{1}`r`n" -f ($Script:RunTimeConfig.ConfigFile.Path), ($Config | ConvertTo-Json) | Write-LogOutput -LogType VERBOSE
            $Success = $false
            do {
                try {
                    if (!$Success) {
                        $Config | ConvertTo-Json | Set-Content ($Script:RunTimeConfig.ConfigFile.Path) -Force
                        $Success = $true
                    }
                }
                catch {
                    if (!$Success) {
                        $ErrorObject = $_
                        "Error writing to file. Retry in 1 second" | Write-LogOutput -LogType WARNING -SkipDialog
                        Start-Sleep -Seconds 1
                    }
                }
            }
            until($Count -ge 10 -or $Success)

            if (!$Success) {
                $ErrorObject.Exception.Message | Write-LogOutput -LogType ERROR -SkipDialog
            }

            $Script:AppConfig = $Config
        }
        catch {
            $_.Exception.Message | Write-LogOutput -LogType ERROR
        }
    }
}

function Invoke-ExecuteScriptAsync {
    PARAM(
        $ScriptToExecute,
        $OnCompletedScriptBlock
    )
    try {

        if ($null -ne $Script:Webview.Object) {
            if ($Script:Webview.Object.IsLoaded) {
                $Script:Task = $Script:Webview.Object.CoreWebView2.ExecuteScriptAsync($ScriptToExecute)
                $Script:Task.GetAwaiter().OnCompleted($OnCompletedScriptBlock)
            }
            else {
                Write-LogOutput -Message "WebView2 is not loaded yet." -LogType DEBUG
            }
        }
        else {
            Write-LogOutput -Message "WebView2 is not initialized." -LogType ERROR
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Invoke-ExecuteScriptWithResultAsync {
    PARAM(
        $ScriptToExecute,
        $OnCompletedScriptBlock
    )
    try {

        if ($null -ne $Script:Webview.Object) {
            if ($Script:Webview.Object.IsLoaded) {
                $Script:Task = $Script:Webview.Object.CoreWebView2.ExecuteScriptWithResultAsync($ScriptToExecute)

                $Script:Task.GetAwaiter().OnCompleted($OnCompletedScriptBlock)
            }
            else {
                Write-LogOutput -Message "WebView2 is not loaded yet." -LogType DEBUG
            }
        }
        else {
            Write-LogOutput -Message "WebView2 is not initialized." -LogType ERROR
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Invoke-LogWindowScrollToEnd {

    try {






        return $true
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Invoke-OmadaPSWebRequestWrapper {
    try {
        try {
            $Private:Parameters = $Script:RunTimeData.RestMethodParam
            $Private:Parameters.AuthenticationType = $($Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content)
            if ($Null -eq $Private:Parameters.Body) {
                if ($Private:Parameters.ContainsKey("Body")) {
                    $Private:Parameters.Remove("Body")
                }
            }
            else {
                if (!$Private:Parameters.ContainsKey("Body")) {
                    $Private:Parameters.Add("Body", $Null)
                }

                $Private:Parameters.Body = $Private:Parameters.Body | ConvertTo-Json
            }
            "Parameters: {0}" -f ($Private:Parameters | ConvertTo-Json -Depth 15) | Write-LogOutput -LogType VERBOSE
            $Private:Result = Invoke-OmadaRestMethod @Parameters
            if($null -ne $Script:MainWindowForm -and $null -ne $Script:MainWindowForm.Definitions -and $Script:MainWindowForm.Definitions.IsVisible){
                $Script:MainWindowForm.Definitions.TextBlockConnectionStatus | Set-TextBlockText -Text "Connected"
            }
            "Result: {0}" -f ($Private:Result | ConvertTo-Json -Depth 15) | Write-LogOutput -LogType VERBOSE
            return $Private:Result
        }
        catch {
            if (![string]::IsNullOrWhiteSpace($_.ErrorDetails?.Message) -and $_.ErrorDetails.Message -like "*Resource not found for the segment 'C_P_SQLTROUBLESHOOTING'*") {
                $Message = "OData Endpoint for SQL Troubleshooting not enabled at tenant {0}.`n`r`n`rError returned by Omada:`n`r`n`r{1}" -f [system.uri]::New($Script:AppConfig.BaseUrl).Host, $_.ErrorDetails.Message
                $Message | Write-LogOutput -LogType ERROR
                if($null -ne $Script:MainWindowForm -and $null -ne $Script:MainWindowForm.Definitions -and $Script:MainWindowForm.Definitions.IsVisible){
                    $Script:MainWindowForm.Definitions.TextBlockConnectionStatus | Set-TextBlockText -Text "Disconnected"
                }
                else{
                    Throw $_
                }
            }
            else{
                Throw $_
            }
        }
    }
    catch {
        Throw $_
    }
}
function Invoke-OnTreeViewItemShiftClick {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', 'Sender', Justification = 'The use of the variable is on purpose')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', 'Args', Justification = 'The use of the variable is on purpose')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Args', Justification = 'The variable is declared because the call contains the parameter')]
    PARAM (
        $Sender,
        $Args
    )

    try {
        "Left shift {0}, Right shift {1}" -f [System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::LeftShift), [System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::RightShift) | Write-LogOutput -LogType VERBOSE

        if ([System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::LeftShift) -or
            [System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::RightShift)) {

            if ($Sender.SelectedItem.IsSelected) {

                $ItemValue = $Sender.SelectedValue.Header.ToString()
                [System.Windows.Clipboard]::SetText($ItemValue)
                "Copied to clipboard: {0}" -f $ItemValue | Write-LogOutput -LogType DEBUG
                if ($null -eq $Script:PreviousLevel) {
                    $Script:PreviousLevel = -1
                }

                switch (Get-TreeviewItemLevel -TreeViewItem $Sender.SelectedItem) {
                    "0" {
                        "Tree view level: {0}, previous: {1}" -f $_, $Script:PreviousLevel | Write-LogOutput -LogType VERBOSE
                        $ItemValue = "{0}." -f $ItemValue.Trim()

                        $Script:PreviousLevel = $_

                    }
                    "1" {
                        "Tree view level: {0}, previous: {1}" -f $_, $Script:PreviousLevel | Write-LogOutput -LogType VERBOSE
                        if ($Script:PreviousLevel -eq 0) {
                            $ItemValue = "{0}" -f $ItemValue.Trim()
                        }
                        else {
                            $ItemValue = " {0}" -f $ItemValue.Trim()
                        }
                        $Script:PreviousLevel = $_
                    }
                    "2" {
                        "Tree view level: {0}, previous: {1}" -f $_, $Script:PreviousLevel | Write-LogOutput -LogType VERBOSE
                        if ($Script:PreviousLevel -eq 1) {
                            $ItemValue = ".{0}" -f ($ItemValue.Trim().Split(" ")[0])
                        }
                        else {
                            $ItemValue = " {0}," -f ($ItemValue.Trim().Split(" ")[0])
                        }
                        $Script:PreviousLevel = $_
                    }
                    default {
                        "Tree view level: {0}" -f $_ | Write-LogOutput -LogType VERBOSE
                    }
                }

                $ScriptToExecute = "try {{
editor.focus();
const position = editor.getPosition();
const range = new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column);
console.log('Range:', range);
editor.executeEdits('', [{{ range, text: '{0}', forceMoveMarkers: true }}]);
console.log('Edit executed successfully');
}} catch (error) {{
console.error('Edit failed:', error);
}}"
 -f $ItemValue

                $Script:SenderTest = $Sender
                "Execute script in in Monaco Editor:`r`n{0}" -f $ScriptToExecute | Write-LogOutput -LogType DEBUG
                $OnCompletedScriptBlock = {
                    try {
                        if (!$Script:Task.Status -eq "RanToCompletion") {
                            "Monaco Editor Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                        }
                        else {
                            "Monaco Editor Task completed successfully: {0}" -f $Script:Task.Result | Write-LogOutput -LogType DEBUG
                        }
                    }
                    catch {
                        $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
                    }
                    if ($null -ne $Script:SenderTest.SelectedItem) {
                        $Script:SenderTest.SelectedItem.IsSelected = $false
                        $Script:MainWindowForm.Definition.Focus()
                        $Script:Webview.Object.Focus()
                    }
                }

                "Set value in Monaco editor." | Write-LogOutput -LogType DEBUG
                Invoke-ExecuteScriptWithResultAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
Function Invoke-SanitizeJsonKeys {
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$JsonString
    )

    $ParsedJson = $JsonString | ConvertFrom-Json -ErrorAction Stop -AsHashtable

    $SanitizedObject = Invoke-SanitizeObject -Data $ParsedJson

    return $SanitizedObject | ConvertTo-Json -Depth 10
}
Function Invoke-SanitizeObject {
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [object]$Data
    )

    if ($Data -is [hashtable]) {
        $NewData = @{}
        foreach ($Key in $Data.Keys) {
            $NewKey = $Key -replace '[^A-Za-z0-9_\-]', $ReplacementChar
            if ($Data[$Key] -is [hashtable]) {
                $NewData[$NewKey] = Invoke-SanitizeObject -Data $Data[$Key]
            }
            elseif ($Data[$Key] -is [array]) {
                $NewData[$NewKey] = $Data[$Key] | ForEach-Object { Invoke-SanitizeObject -Data $_ }
            }
            else {
                $NewData[$NewKey] = $Data[$Key]
            }
        }
        return $NewData
    }
    elseif ($Data -is [array]) {
        return $Data | ForEach-Object { Invoke-SanitizeObject -Data $_ }
    }
    else {
        return $Data
    }
}
function Invoke-SaveAndExecuteQuery {


    try {

        if(!(Test-ConnectionRequirements)){
            "Connection not ready" | Write-LogOutput -LogType DEBUG
            return
        }

        $ScriptToExecute = "editor.getValue();"

        $OnCompletedScriptBlock = {
            try {
                if ($Script:Task.Status -eq "RanToCompletion") {
                    $Script:RunTimeData.QueryText = $Script:Task.Result
                    if (![string]::IsNullOrWhiteSpace($Script:RunTimeData.QueryText.ResultAsJson)) {
                        $Script:RunTimeData.QueryText = $Script:RunTimeData.QueryText.ResultAsJson | ConvertFrom-Json
                    }

                    $Private:Result = Get-SqlQueryObject

                    "Executing SQL Query: {0}" -f $Script:RunTimeData.QueryText | Write-LogOutput -LogType DEBUG
                    $Script:RunTimeData.RestMethodParam.Body = @{}
                    $Script:RunTimeData.RestMethodParam.Uri = "{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING({1})" -f $Script:AppConfig.BaseUrl, $Script:AppConfig.CurrentSqlQuery.DoId
                    if ($Script:RunTimeData.CurrentQueryText -ne $Script:RunTimeData.QueryText -or $Script:RunTimeData.QueryText -ne $Private:Result.C_QUERY) {
                        "Update current query for DODI: {0}" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput -LogType DEBUG
                        $Script:RunTimeData.RestMethodParam.Body.Add("C_QUERY", $Script:RunTimeData.QueryText)
                        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentDataConnection.DoId)) {
                            $Script:RunTimeData.RestMethodParam.Body.Add("C_SQLTROUBLESHOOTING_DATACONNECTION", @{Id = $Script:AppConfig.CurrentDataConnection.DoId })
                        }
                    }
                    if ($Script:RunTimeData.CurrentSqlQuery.DisplayName -ne $Script:MainWindowForm.Elements.TextBoxDisplayName.Text) {
                        $Script:RunTimeData.RestMethodParam.Body.Add("NAME", $Script:MainWindowForm.Elements.TextBoxDisplayName.Text)
                    }
                    if (($Script:RunTimeData.RestMethodParam.Body.Keys | Measure-Object).Count -le 0) {
                        "No changes detected! Just run query" | Write-LogOutput -LogType DEBUG
                    }
                    else {
                        "Body: {0}" -f ($Script:RunTimeData.RestMethodParam.Body | ConvertTo-Json) | Write-LogOutput -LogType VERBOSE
                        "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG

                        "Save query" | Write-LogOutput
                        $Script:RunTimeData.RestMethodParam.Method = "PUT"
                        $Private:Result = Invoke-OmadaPSWebRequestWrapper
                        "Query saved!" | Write-LogOutput
                    }
                    $Script:RunTimeData.RestMethodParam.Uri = "{0}/webservice/jQGridPopulationWebService.asmx/GetPagingData" -f $Script:AppConfig.BaseUrl

                    $Script:RunTimeData.RestMethodParam.Body = @{
                        "dataType"     = "SqlDataProducer"
                        "dataTypeArgs" = @{
                            "targetId" = $Script:AppConfig.CurrentSqlQuery.DoId
                        }
                        "page"         = 1
                        "rows"         = 100000
                        "sidx"         = $Null
                        "sord"         = "asc"
                        "_search"      = $False
                        "searchField"  = $Null
                        "searchString" = $Null
                        "filters"      = $Null
                        "searchOper"   = $Null
                    }
                    "Body: {0}" -f ($Script:RunTimeData.RestMethodParam.Body | ConvertTo-Json) | Write-LogOutput -LogType VERBOSE
                    "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG

                    "Retrieve query output, please wait..." | Write-LogOutput
                    $Script:RunTimeData.RestMethodParam.Method = "POST"
                    $Script:RunTimeData.QueryResult = $null
                    $Script:RunTimeData.QueryResult = Invoke-OmadaPSWebRequestWrapper


                    if ($null -ne $Script:RunTimeData.QueryResult -and ($Script:RunTimeData.QueryResult.d.Rows | Measure-Object).Count -le 0) {
                        "Query did not return any results!" | Write-LogOutput -LogType WARNING
                        $Script:MainWindowForm.Elements.TextBlockRows | Set-TextBlockText -Text "0 rows"
                    }
                    else {
                        $Script:MainWindowForm.Elements.DataGridQueryResult.AutoGenerateColumns = $true
                        try{
                            $Script:MainWindowForm.Elements.DataGridQueryResult.ItemsSource = @($Script:RunTimeData.QueryResult.d.Rows)
                        }
                        catch{
                            $Script:MainWindowForm.Elements.DataGridQueryResult.ItemsSource = @(($Script:RunTimeData.QueryResult | ConvertTo-Json -Depth 10 | Invoke-SanitizeJsonKeys | ConvertFrom-Json -Depth 10).d.Rows)
                        }
                        "Result:`r`n{0}" -f ($Script:RunTimeData.QueryResult.d.rows | Format-Table -AutoSize | Out-String -Width 10000000 ) | Write-LogOutput
                        $Script:MainWindowForm.Elements.ButtonShowOutput.IsEnabled = $True
                        $Script:MainWindowForm.Elements.ButtonSaveOutputFile.IsEnabled = $True
                        "{0} record(s) retrieved!" -f $Script:RunTimeData.QueryResult.d.Records | Write-LogOutput

                        $Script:MainWindowForm.Elements.TextBlockRows | Set-TextBlockText -Text ("{0:n0} rows" -f [Int]$Script:RunTimeData.QueryResult.d.Records)
                        $Private:Result.Id,$Private:Result.DisplayName | Invoke-ConfigSetting -Property "CurrentSqlQuery"
                        if ($Private:Result.DisplayName -ne $Script:RunTimeData.CurrentSqlQuery.DisplayName) {
                            "New display name, Current: {0}, New: {1}" -f $Script:RunTimeData.CurrentSqlQuery.DisplayName, $Private:Result.DisplayName | Write-LogOutput -LogType DEBUG
                            "Force update query list" | Write-LogOutput -LogType DEBUG
                            Update-QueryList -ForceRefresh
                            $ComboBoxSelectQueryItem = $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items | Where-Object { $_.Content -eq $Script:AppConfig.CurrentSqlQuery.FullName }
                            if ($null -ne $ComboBoxSelectQueryItem) {
                                $ComboBoxSelectQueryItem = New-Object System.Windows.Controls.ComboBoxItem
                                $ComboBoxSelectQueryItem.Content = $Script:AppConfig.CurrentSqlQuery.FullName
                                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Add($ComboBoxSelectQueryItem) | Out-Null
                            }
                            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $ComboBoxSelectQueryItem
                        }
                    }
                }
                elseif ($Script:Task.Status -eq "Faulted") {
                    "Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                }
                else {
                    "Task result: {0}" -f $Script:Task.Status | Write-LogOutput -LogType DEBUG
                }
                $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonExecuteQuery | Set-ButtonContent -Content "_Execute Query"
                if($null -ne $Script:PopupWindowExecuteQuery) {
                    $Script:PopupWindowExecuteQuery.Close()
                }

                if ($null -ne $Script:RunTimeData.StopWatch) {
                    $Script:RunTimeData.StopWatch.Stop()
                    "Elapsed time: {0}" -f $Script:RunTimeData.StopWatch.Elapsed.ToString() | Write-LogOutput -Debug
                    $Script:MainWindowForm.Elements.TextBlockQueryTime.Text = $Script:RunTimeData.StopWatch.Elapsed.ToString()
                }
            }
            catch {
                $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonExecuteQuery | Set-ButtonContent -Content "_Execute Query"
                if($null -ne $Script:PopupWindowExecuteQuery) {
                    $Script:PopupWindowExecuteQuery.Close()
                }
                $_.Exception.Message | Write-LogOutput -LogType ERROR
            }
        }
        Invoke-ExecuteScriptWithResultAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
    }
    catch {
        if ($null -ne $Script:RunTimeData.StopWatch) {
            $Script:RunTimeData.StopWatch.Stop()
            $Script:MainWindowForm.Elements.TextBlockQueryTime.Text = $Script:RunTimeData.StopWatch.Elapsed.ToString()
        }
        $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
        $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
        $Script:MainWindowForm.Elements.ButtonExecuteQuery | Set-ButtonContent -Content "_Execute Query"
        if($null -ne $Script:PopupWindowExecuteQuery) {
            $Script:PopupWindowExecuteQuery.Close()
        }

        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Invoke-SaveQuery {
    PARAM(
        [switch]$NewQuery
    )

    try {
        $ScriptToExecute = "editor.getValue();"
        $Script:NewQuery = $NewQuery
        $OnCompletedScriptBlock = {
            try {
                if ($Script:Task.Status -eq "RanToCompletion") {
                    $Script:RunTimeData.QueryText = $Script:Task.Result
                    if (![string]::IsNullOrWhiteSpace($Script:RunTimeData.QueryText.ResultAsJson)) {
                        $Script:RunTimeData.QueryText = $Script:RunTimeData.QueryText.ResultAsJson | ConvertFrom-Json
                    }

                    if ($Script:NewQuery) {
                        "Create new query" | Write-LogOutput -LogType DEBUG

                        $Script:RunTimeData.RestMethodParam.Uri = '{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING?$filter=Deleted ne true and NAME eq ''{1}''' -f $Script:AppConfig.BaseUrl, $Script:MainWindowForm.Elements.TextBoxDisplayName.Text
                        "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG
                        "Check if a query with this name already exists" | Write-LogOutput -LogType DEBUG
                        $Script:RunTimeData.RestMethodParam.Body = $Null
                        $Script:RunTimeData.RestMethodParam.Method = "GET"
                        $Script:RunTimeData.RestMethodParam.Body = $null
                        $CheckIfExistResult = Invoke-OmadaPSWebRequestWrapper
                        if ($null -eq $CheckIfExistResult -or ($CheckIfExistResult.Value | Measure-Object).Count -le 0) {
                            $Script:RunTimeData.RestMethodParam.Uri = "{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING" -f $Script:AppConfig.BaseUrl
                            $Script:RunTimeData.RestMethodParam.Method = "POST"
                        }
                        else {
                            $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
                            $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
                            "Query with this name already exists!" | Write-LogOutput -LogType ERROR
                            return
                        }
                    }
                    else {
                        "Save existing query" | Write-LogOutput -LogType DEBUG
                        $Script:RunTimeData.RestMethodParam.Uri = "{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING({1})" -f $Script:AppConfig.BaseUrl, $Script:AppConfig.CurrentSqlQuery.DoId
                        $private:Result = Get-SqlQueryObject
                        $Script:RunTimeData.RestMethodParam.Method = "PUT"
                    }
                    $Script:RunTimeData.RestMethodParam.Body = @{}
                    if ($Script:NewQuery -or ($Script:RunTimeData.CurrentQueryText -ne $Script:RunTimeData.QueryText -or $Script:RunTimeData.QueryText -ne $private:Result.C_QUERY)) {
                        $Script:RunTimeData.RestMethodParam.Body.Add("C_QUERY", $Script:RunTimeData.QueryText)
                        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentDataConnection.DoId)) {
                            $Script:RunTimeData.RestMethodParam.Body.Add("C_SQLTROUBLESHOOTING_DATACONNECTION", @{Id = $Script:AppConfig.CurrentDataConnection.DoId })
                        }
                    }
                    if ($Script:RunTimeData.CurrentSqlQuery.DisplayName -ne $Script:MainWindowForm.Elements.TextBoxDisplayName.Text) {
                        $Script:RunTimeData.RestMethodParam.Body.Add("NAME", $Script:MainWindowForm.Elements.TextBoxDisplayName.Text)
                    }
                    if (!$Script:NewQuery -and ($Script:RunTimeData.RestMethodParam.Body.Keys | Measure-Object).Count -le 0) {
                        "No changes detected! Saving not needed." | Write-LogOutput -LogType DEBUG
                    }
                    else {
                        "Saving SQL Query: {0}" -f $Script:RunTimeData.QueryText | Write-LogOutput -LogType DEBUG
                        "Body: {0}" -f ($Script:RunTimeData.RestMethodParam.Body | ConvertTo-Json) | Write-LogOutput -LogType VERBOSE
                        "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG

                        "Save query" | Write-LogOutput
                        $private:Result = Invoke-OmadaPSWebRequestWrapper

                        if ($null -ne $private:Result -and $Script:NewQuery -or $private:Result.DisplayName -ne $Script:RunTimeData.CurrentSqlQuery.DisplayName) {
                            "Query saved!" | Write-LogOutput
                            if ($Script:NewQuery) {
                                $Script:RunTimeData.CurrentSqlQuery.DoId = $private:Result.Id
                                $Script:RunTimeData.CurrentSqlQuery.DisplayName = $private:Result.Name
                                $private:Result.Id, $private:Result.Name | Invoke-ConfigSetting -Property "CurrentSqlQuery"
                                $ComboBoxSelectQueryItem = New-Object System.Windows.Controls.ComboBoxItem
                                $ComboBoxSelectQueryItem.Content = $Script:RunTimeData.CurrentSqlQuery.DoId
                                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Add($ComboBoxSelectQueryItem) | Out-Null
                            }
                            else {
                                "New display name, Current: {0}, New: {1}" -f $Script:RunTimeData.CurrentSqlQuery.DisplayName, $private:Result.DisplayName | Write-LogOutput -LogType VERBOSE
                                "Force update query list" | Write-LogOutput -LogType DEBUG
                                Update-QueryList -ForceRefresh
                                $Script:RunTimeData.CurrentSqlQuery.DoId = $Script:AppConfig.CurrentSqlQuery.DoId
                                $ComboBoxSelectQueryItem = $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items | Where-Object { $_.Content -eq $Script:RunTimeData.CurrentSqlQuery.DoId }
                                if ($null -eq $ComboBoxSelectQueryItem) {
                                    $ComboBoxSelectQueryItem = New-Object System.Windows.Controls.ComboBoxItem
                                    $ComboBoxSelectQueryItem.Content = $Script:RunTimeData.CurrentSqlQuery.DoId
                                    $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Add($ComboBoxSelectQueryItem) | Out-Null
                                }
                            }
                            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $ComboBoxSelectQueryItem
                            $Script:RunTimeData.CurrentSqlQuery.DisplayName = $private:Result.DisplayName
                        }
                    }
                }
                elseif ($Script:Task.Status -eq "Faulted") {
                    "Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                }
                else {
                    "Task result: {0}" -f $Script:Task.Status | Write-LogOutput -LogType DEBUG
                }
                $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
            }
            catch {
                $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
            }
        }
        Invoke-ExecuteScriptWithResultAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function New-FormObject {
    PARAM (
        [parameter(Mandatory = $False)]
        [validateScript({ Test-Path $_ -PathType Leaf })]
        $FormPath,
        [parameter(Mandatory = $False)]
        $Xaml,
        [parameter(Mandatory = $False)]
        $ParentForm
    )
    try {
        if ($null -eq $FormPath -and $null -eq $Xaml) {
            "Either FormPath or Xaml must be provided!" | Write-LogOutput -LogType ERROR
            break
        }

        if ($null -ne $FormPath) {
            [xml]$Xaml = Get-Content $FormPath -Raw
        }

        $NamespaceManager = New-Object System.Xml.XmlNamespaceManager($Xaml.NameTable)
        $NamespaceManager.AddNamespace("default", "http://schemas.microsoft.com/winfx/2006/xaml/presentation")
        $NamespaceManager.AddNamespace("x", "http://schemas.microsoft.com/winfx/2006/xaml")
        $NamespaceManager.AddNamespace("Wpf", "clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf")

        $Reader = (New-Object System.Xml.XmlNodeReader $Xaml)
        $Form = [Windows.Markup.XamlReader]::Load($Reader)
        "Create form: {0}" -f $Form.Name | Write-LogOutput -LogType DEBUG
        $Form.Icon = Get-Icon -Type Wpf

        $Elements = @()
        $ElementNames = @("ComboBox", "Label", "TextBox", "Button", "CheckBox", "RadioButton", "PasswordBox", "ComboBoxItem", "WebView2", "DataGrid", "TextBlock", "TreeViewSqlSchema")
        foreach ($ElementName in $ElementNames) {
            "Find element type: {0}" -f $ElementName | Write-LogOutput -LogType DEBUG
            $Xaml.DocumentElement.SelectNodes("//default:$ElementName", $NamespaceManager) | ForEach-Object {
                $_.Name | Select-Object -Unique | ForEach-Object {
                    if (![string]::IsNullOrWhiteSpace($_) -and $null -ne $Form.FindName($_)) {
                        "Add element type: {0}" -f $_ | Write-LogOutput -LogType DEBUG
                        $Elements += @{
                            "$_" = $Form.FindName($_)
                        }
                    }
                }
            }
        }

        if ($null -ne $ParentForm) {
            "Parent form: {0}" -f $ParentForm.Name | Write-LogOutput -LogType DEBUG
            $Form.Owner = $ParentForm
            "Form Height: {0}" -f $Form.Height | Write-LogOutput -LogType DEBUG
            "Parent form Height: {0}" -f $ParentForm.Height | Write-LogOutput -LogType DEBUG
            if([double]::IsNaN($Form.Height)){
                $Form.Height = $ParentForm.Height
            }
            else{
                $Form.Height = [math]::Max($Form.Height, $ParentForm.Height)
            }
            if($Form.Width -eq "NaN"){
                $Form.Width = $Form.MinWidth
            }
        }

        "Form Dimensions: {0}x{1}" -f  $Form.Width,$Form.Height | Write-LogOutput -LogType DEBUG
        "Form Location: {0}x{1}" -f $Form.Left, $Form.Top | Write-LogOutput -LogType DEBUG

        "Return form object for: {0}" -f $Form.Name | Write-LogOutput -LogType DEBUG

        return [PSCustomObject]@{
            Definition      = $Form
            Elements        = $Elements
            Xaml            = $Xaml
            Position        = [PSCustomObject]@{
                Left = $null
                Top  = $null
            }
            Size            = [PSCustomObject]@{
                Width  = $Form.MinWidth
                Height = $Form.MinHeight
            }
            State           = "NotOpenend"
            PositionManager = @{
                Synchronizing       = $false
                PositionOffSetLeft  = 0
                PositionOffSetRight = 0
                PositionOffSetTop   = 0
                MainWindowRight     = 0
                MainWindowBottom    = 0
                ChildWindowLeft     = 0
                ChildWindowRight    = 0
                ChildWindowBottom   = 0
                LastPositionChange  = Get-Date
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Open-LogWindow {
    try {
        "Opening Log window" | Write-LogOutput -LogType DEBUG
        $Script:LogWindowForm = New-FormObject -FormPath (Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "lib\ui\LogWindow.xaml") -ParentForm $Script:MainWindowForm.Definition
        [Int]$Script:LogWindowForm.PositionManager.PositionOffSetLeft = 1200

        $true | Invoke-ConfigSetting -Property "LogWindowFormOpen"

        $Script:LogWindowForm.Definition.ShowInTaskbar = $false
        $Script:TextBoxLog = $Script:LogWindowForm.Definition.FindName("TextBoxLog")
        if ($Script:AppConfig.LogWindowWordWrap) {
            $Script:TextBoxLog.TextWrapping = "WrapWithOverflow"
            $Script:LogWindowForm.Elements.CheckboxWordWrap.IsChecked = $true
            "Word wrap is enabled" | Write-LogOutput -LogType LOG
            $true | Invoke-ConfigSetting -Property "LogWindowWordWrap"
        }
        else {
            $Script:TextBoxLog.TextWrapping = "NoWrap"
            $Script:LogWindowForm.Elements.CheckboxWordWrap.IsChecked = $false
            $false | Invoke-ConfigSetting -Property "LogWindowWordWrap"
        }
        if ($Script:RunTimeConfig.LogToConsole) {
            $Script:LogWindowForm.Elements.CheckboxConsoleLog.IsChecked = $true
            "Console logging is enabled" | Write-LogOutput -LogType LOG
            $true | Invoke-ConfigSetting -Property "CheckboxConsoleLog"
        }
        else {
            $Script:LogWindowForm.Elements.CheckboxConsoleLog.IsChecked = $false
            $false | Invoke-ConfigSetting -Property "CheckboxConsoleLog"
        }

        if (![string]::IsNullOrWhiteSpace($Script:AppConfig.LogLevel)) {
            "Set window log level to: {0}" -f $Script:AppConfig.LogLevel | Write-LogOutput -LogType DEBUG
            if (($LogWindowForm.Elements.ComboBoxSelectLogLevel.Items | Measure-Object).count -le 0 -and !$LogWindowForm.Elements.ComboBoxSelectLogLevel.Items.Content.Contains($Script:AppConfig.LogLevel)) {
                $ComboBoxSelectLogLevelItem = New-Object System.Windows.Controls.ComboBoxItem
                $ComboBoxSelectLogLevelItem.Content = $Script:AppConfig.LogLevel
                $LogWindowForm.Elements.ComboBoxSelectLogLevel.Items.Add($ComboBoxSelectLogLevelItem) | Out-Null
            }
            $LogWindowForm.Elements.ComboBoxSelectLogLevel.SelectedValue = $LogWindowForm.Elements.ComboBoxSelectLogLevel.Items | Where-Object { $_.Content -eq $Script:AppConfig.LogLevel }
            $Script:RunTimeConfig.Logging.LogLevelSetting = $Script:AppConfig.LogLevel
        }
        else {
            "Set window log level to default because it was not set: INFO" | Write-LogOutput -LogType DEBUG
            if (($LogWindowForm.Elements.ComboBoxSelectLogLevel.Items | Measure-Object).count -le 0 -and !$LogWindowForm.Elements.ComboBoxSelectLogLevel.Items.Content.Contains("INFO")) {
                $ComboBoxSelectLogLevelItem = New-Object System.Windows.Controls.ComboBoxItem
                $ComboBoxSelectLogLevelItem.Content = "INFO"
                $LogWindowForm.Elements.ComboBoxSelectLogLevel.Items.Add($ComboBoxSelectLogLevelItem) | Out-Null
            }
            $LogWindowForm.Elements.ComboBoxSelectLogLevel.SelectedValue = $LogWindowForm.Elements.ComboBoxSelectLogLevel.Items | Where-Object { $_.Content -eq "INFO" }
            $Script:RunTimeConfig.Logging.LogLevelSetting = $LogWindowForm.Elements.ComboBoxSelectLogLevel.SelectedValue.Content
        }


        $Script:LogWindowForm.Definition.Add_LocationChanged({
                $_ | Show-EventInfo -LogType VERBOSE2
                if (!$Script:LogWindowForm.PositionManager.Synchronizing) {
                    $Script:LogWindowForm.PositionManager.Synchronizing = $true
                    "MainWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:MainWindowForm.Definition.Left, $Script:MainWindowForm.Definition.Top, $Script:MainWindowForm.Definition.Width , $Script:MainWindowForm.Definition.Height | Write-LogOutput -LogType VERBOSE2
                    "LogWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:LogWindowForm.Definition.Left, $Script:LogWindowForm.Definition.Top, $Script:LogWindowForm.Definition.Width , $Script:LogWindowForm.Definition.Height | Write-LogOutput -LogType VERBOSE2
                    $Script:LogWindowForm.Definition.Dispatcher.Invoke({
                            $_ | Show-EventInfo -LogType VERBOSE2
                            $Script:LogWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:LogWindowForm.Definition.Left) - [Int]::Abs($Script:MainWindowForm.Definition.Left)
                            "PositionManagerLogWindow PositionOffSetLeft: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType VERBOSE2
                            $Script:LogWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:LogWindowForm.Definition.Top) - [Int]::Abs($Script:MainWindowForm.Definition.Top)
                            "PositionManagerLogWindow PositionOffSetTop: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetTop | Write-LogOutput -LogType VERBOSE2
                            $Script:LogWindowForm.PositionManager.Synchronizing = $false
                        }, [System.Windows.Threading.DispatcherPriority]::Render)
                }
            })

        $Script:LogWindowForm.Definition.Add_SizeChanged({
                $_ | Show-EventInfo -LogType VERBOSE2
                $Script:LogWindowForm.Size = $Script:LogWindowForm.Definition | Get-WindowSize
            })


        if ($null -ne ($Script:LogWindowForm.Definition | Get-WindowPositionConfig)) {
            $Position = $Script:LogWindowForm.Definition | Get-WindowPositionConfig
            "Log window position: {0}" -f $Position | Write-LogOutput -LogType DEBUG
            $Script:LogWindowForm.Definition.Left = [Int]::Abs($Position.Split("x")[0])
            $Script:LogWindowForm.Definition.Top = [Int]::Abs($Position.Split("x")[1])
        }

        $Script:LogWindowForm.Definition.Add_Loaded({
                $_ | Show-EventInfo
                $Script:LogWindowForm.PositionManager.Synchronizing = $true
                $Script:LogWindowForm.Definition.Dispatcher.Invoke({
                        "MainWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:MainWindowForm.Definition.Left, $Script:MainWindowForm.Definition.Top, $Script:MainWindowForm.Definition.Width , $Script:MainWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                        $Script:LogWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top)
                        "LogWindowForm Top: {0}" -f $Script:LogWindowForm.Definition.Top | Write-LogOutput -LogType DEBUG
                        $Script:LogWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) + [Int]::Abs($Script:MainWindowForm.Definition.Width)
                        "LogWindowForm Left: {0}" -f $Script:LogWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG
                        $Script:LogWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:LogWindowForm.Definition.Left) - [Int]::Abs($Script:MainWindowForm.Definition.Left)
                        "PositionManagerLogWindow PositionOffSetLeft: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType DEBUG
                        $Script:LogWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:LogWindowForm.Definition.Top) - [Int]::Abs($Script:MainWindowForm.Definition.Top)
                        "PositionManagerLogWindow PositionOffSetTop: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetTop | Write-LogOutput -LogType DEBUG
                        if ($null -ne ($Script:LogWindowForm.Definition | Get-WindowSizeConfig)) {
                            $Size = $Script:LogWindowForm.Definition | Get-WindowSizeConfig
                            "Log window size: {0}" -f $Size | Write-LogOutput -LogType DEBUG
                            $Script:LogWindowForm.Definition.Width = [Int]::Abs($Size.Split("x")[0])
                            "LogWindowForm Width: {0}" -f $Script:LogWindowForm.Definition.Width | Write-LogOutput -LogType DEBUG
                            $Script:LogWindowForm.Definition.Height = [Int]::Abs($Size.Split("x")[1])
                            "LogWindowForm Height: {0}" -f $Script:LogWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                        }
                        $Script:LogWindowForm.PositionManager.Synchronizing = $false
                    }, [System.Windows.Threading.DispatcherPriority]::Render)
                $Script:MainWindowForm.Elements.ButtonShowLog | Set-ButtonContent -Content "_Hide Log"
                $Script:TextBoxLog.Text = $Script:RunTimeConfig.Logging.AppLogObject
                $Script:LogWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:LogWindowForm.Definition.Left) - [Int]::Abs($Script:MainWindowForm.Definition.Left)
                "PositionManagerLogWindow PositionOffSetLeft: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType DEBUG
                $Script:LogWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:LogWindowForm.Definition.Top) - [Int]::Abs($Script:MainWindowForm.Definition.Top)
                "PositionManagerLogWindow PositionOffSetTop: {0}" -f $Script:LogWindowForm.PositionManager.PositionOffSetTop | Write-LogOutput -LogType DEBUG
                "LogWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:LogWindowForm.Definition.Left, $Script:LogWindowForm.Definition.Top, $Script:LogWindowForm.Definition.Width , $Script:LogWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                $Script:LogWindowForm.State = "Open"
            })

        $Script:LogWindowForm.Definition.Add_Closing({
                $_ | Show-EventInfo
                $Script:LogWindowForm.State = "Closing"
                Save-WindowMeasurements
                if ($Script:MainWindowForm.State -eq "Open") {
                    $false | Invoke-ConfigSetting -Property "LogWindowFormOpen"
                }
            })

        $Script:LogWindowForm.Definition.Add_Closed({
                $_ | Show-EventInfo
                $Script:LogWindowForm.State = "Closed"
                $Script:MainWindowForm.Elements.ButtonShowLog | Set-ButtonContent -Content "Log"
            })

        $Script:LogWindowForm.Elements.ButtonClearLog.Add_Click({
                $_ | Show-EventInfo
                "Clear TextBoxLog" | Write-LogOutput -LogType DEBUG
                $Script:TextBoxLog.Clear()
                "Log cleared" | Write-LogOutput
            })

        $Script:TextBoxLog.remove_TextChanged({
                $_ | Show-EventInfo
                "Clear AppLogObject" | Write-LogOutput -LogType DEBUG
                $Script:RunTimeConfig.Logging.AppLogObject.Clear()
            })

        $Script:LogWindowForm.Elements.ButtonExportLogFile.Add_Click({
                $_ | Show-EventInfo
                $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
                $SaveFileDialog.Filter = "Log files (*.log) | *.log | All files (*.*) | *.*"
                "Dialog Filter: {0}" -f $SaveFileDialog.Filter | Write-LogOutput -LogType DEBUG
                $SaveFileDialog.Title = "Save Log File"
                "Dialog Title: {0}" -f $SaveFileDialog.Title | Write-LogOutput -LogType DEBUG
                $SaveFileDialog.FileName = "OmadaSqlTroubleShooter.log"
                "Dialog Initial FileName: {0}" -f $SaveFileDialog.FileName | Write-LogOutput -LogType DEBUG
                if ($SaveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
                    if ($Null -eq $SaveFileDialog.FileName) {
                        return
                    }
                    else {
                        $Script:RunTimeConfig.Logging.AppLogObject | Set-Content $SaveFileDialog.FileName -Encoding UTF8
                        "File saved to: {0}" -f $SaveFileDialog.FileName | Write-LogOutput -LogType DEBUG

                    }
                }
                else {
                    "File was not saved!" | Write-LogOutput -LogType DEBUG
                }
            })

        $Script:LogWindowForm.Elements.ComboBoxSelectLogLevel.Add_SelectionChanged({
                $_ | Show-EventInfo
                $Script:LogWindowForm.Elements.ComboBoxSelectLogLevel.SelectedItem.Content | Invoke-ConfigSetting -Property "LogLevel"
                $Script:RunTimeConfig.Logging.LogLevelSetting = $Script:LogWindowForm.Elements.ComboBoxSelectLogLevel.SelectedItem.Content
                "Logging set to {0}!" -f $Script:RunTimeConfig.Logging.LogLevelSetting | Write-LogOutput -LogType LOG
            })


        $Script:LogWindowForm.Elements.CheckboxWordWrap.Add_Checked({
                $_ | Show-EventInfo
                $Script:TextBoxLog.TextWrapping = "WrapWithOverflow"
                "Word wrap is enabled" | Write-LogOutput -LogType LOG
                $true | Invoke-ConfigSetting -Property "LogWindowWordWrap"
            })

        $Script:LogWindowForm.Elements.CheckboxWordWrap.Add_UnChecked({
                $_ | Show-EventInfo
                $Script:TextBoxLog.TextWrapping = "NoWrap"
                "Word wrap is disabled" | Write-LogOutput -LogType LOG
                $false | Invoke-ConfigSetting -Property "LogWindowWordWrap"

            })

        $Script:LogWindowForm.Elements.CheckboxConsoleLog.Add_Checked({
                $_ | Show-EventInfo
                $Script:RunTimeConfig.LogToConsole = $true
                "Console logging is enabled" | Write-LogOutput -LogType LOG
                $true | Invoke-ConfigSetting -Property "CheckboxConsoleLog"
            })

        $Script:LogWindowForm.Elements.CheckboxConsoleLog.Add_UnChecked({
                $_ | Show-EventInfo
                $Script:RunTimeConfig.LogToConsole = $false
                "Console logging is disabled" | Write-LogOutput -LogType LOG
                $false | Invoke-ConfigSetting -Property "CheckboxConsoleLog"

            })

        $Script:LogWindowForm.Definition.Show()
        if ($Script:TextBoxLog.IsLoaded -and (Invoke-LogWindowScrollToEnd)) {
            $Script:TextBoxLog.ScrollToEnd()
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Open-SplashScreenForm {
    try {

        "Loading Splash Screen" | Write-LogOutput -LogType DEBUG
        $SplashScreenForm = New-Object System.Windows.Forms.Form
        $SplashScreenForm.Text = "Loading..."
        $SplashScreenForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None
        $SplashScreenForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
        $SplashScreenForm.Width = 300
        $SplashScreenForm.Height = 250
        $SplashScreenForm.BackColor = [System.Drawing.Color]::White

        $LogoPictureBox = New-Object System.Windows.Forms.PictureBox
        $LogoPictureBox.Image = Get-Icon -Type WinForms
        $LogoPictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
        $LogoPictureBox.Width = 150
        $LogoPictureBox.Height = 150
        $LogoPictureBox.Location = New-Object System.Drawing.Point(65, 20)
        $SplashScreenForm.Controls.Add($LogoPictureBox)

        $SplashLabel = New-Object System.Windows.Forms.Label
        $SplashLabel.Text = "Initializing application..."
        $SplashLabel.Font = New-Object System.Drawing.Font("Segoe UI", 12, [System.Drawing.FontStyle]::Bold)
        $SplashLabel.AutoSize = $True
        $SplashLabel.Location = New-Object System.Drawing.Point(55, 180)
        $SplashScreenForm.Controls.Add($SplashLabel)
        return $SplashScreenForm

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Open-SqlSchemaWindow {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', 'Sender', Justification = 'The use of the variable is on purpose')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', 'Args', Justification = 'The use of the variable is on purpose')]
    PARAM()
    try {
        "Opening Sql Schema window" | Write-LogOutput -LogType DEBUG
        $Script:SqlSchemaWindowForm = New-FormObject -FormPath (Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "lib\ui\SqlSchemaWindow.xaml") -ParentForm $Script:MainWindowForm.Definition
        [Int]$Script:SqlSchemaWindowForm.PositionManager.PositionOffSetRight = 405


        $true | Invoke-ConfigSetting -Property "SqlSchemaWindowFormOpen"

        $Script:SqlSchemaWindowForm.Definition.ShowInTaskbar = $false
        $Script:TreeViewSqlSchema = $Script:SqlSchemaWindowForm.Definition.FindName("TreeViewSqlSchema")

        $Script:TreeViewSqlSchema.Add_SelectedItemChanged({
                param ($Sender, $Args)
                $_ | Show-EventInfo
                Invoke-OnTreeViewItemShiftClick -sender $Sender -args $Args
            })



        $Script:SqlSchemaWindowForm.Definition.Add_LocationChanged({
                $_ | Show-EventInfo -LogType VERBOSE2
                if (!$Script:SqlSchemaWindowForm.PositionManager.Synchronizing) {
                    $Script:SqlSchemaWindowForm.PositionManager.Synchronizing = $true
                    "MainWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:MainWindowForm.Definition.Left, $Script:MainWindowForm.Definition.Top, $Script:MainWindowForm.Definition.Width , $Script:MainWindowForm.Definition.Height | Write-LogOutput -LogType VERBOSE2
                    "SqlSchemaWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:SqlSchemaWindowForm.Definition.Left, $Script:SqlSchemaWindowForm.Definition.Top, $Script:SqlSchemaWindowForm.Definition.Width , $Script:SqlSchemaWindowForm.Definition.Height | Write-LogOutput -LogType VERBOSE2
                    $Script:SqlSchemaWindowForm.Definition.Dispatcher.Invoke({
                            $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Top)
                            "PositionManagerSqlSchemaWindow PositionOffSetLeft: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType VERBOSE2
                            $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:MainWindowForm.Definition.Left) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Left)
                            "PositionManagerSqlSchemaWindow PositionOffSetTop: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetTop | Write-LogOutput -LogType VERBOSE2
                            $Script:SqlSchemaWindowForm.PositionManager.Synchronizing = $false
                        }, [System.Windows.Threading.DispatcherPriority]::Render)
                }
            })

        $Script:SqlSchemaWindowForm.Definition.Add_SizeChanged({
                $_ | Show-EventInfo -LogType VERBOSE2
                $Script:SqlSchemaWindowForm.Size = $Script:SqlSchemaWindowForm.Definition | Get-WindowSize
            })


        if ($null -ne ($Script:SqlSchemaWindowForm.Definition | Get-WindowPositionConfig)) {
            $Position = $Script:SqlSchemaWindowForm.Definition | Get-WindowPositionConfig
            "Sql Schema window position: {0}" -f $Position | Write-LogOutput -LogType DEBUG
            $Script:SqlSchemaWindowForm.Definition.Left = [Int]::Abs($Position.Split("x")[0])
            $Script:SqlSchemaWindowForm.Definition.Top = [Int]::Abs($Position.Split("x")[1])
        }



        $Script:SqlSchemaWindowForm.Definition.Add_Loaded({
                $_ | Show-EventInfo

                Get-SqlSchemaObject

                $Script:SqlSchemaWindowForm.PositionManager.Synchronizing = $true
                $Script:SqlSchemaWindowForm.Definition.Dispatcher.Invoke({
                        $Script:SqlSchemaWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top)
                        "MainWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:MainWindowForm.Definition.Left, $Script:MainWindowForm.Definition.Top, $Script:MainWindowForm.Definition.Width , $Script:MainWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                        $Script:SqlSchemaWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Width)
                        "SqlSchemaWindowForm Left: {0}" -f $Script:SqlSchemaWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG
                        $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Top)
                        $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:MainWindowForm.Definition.Left) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Left)
                        "PositionManagerSqlSchemaWindow PositionOffSetLeft: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType DEBUG
                        if ($null -ne ($Script:SqlSchemaWindowForm.Definition | Get-WindowSizeConfig)) {
                            $Size = $Script:SqlSchemaWindowForm.Definition | Get-WindowSizeConfig
                            "Sql Schema window size: {0}" -f $Size | Write-LogOutput -LogType DEBUG
                            $Script:SqlSchemaWindowForm.Definition.Width = $Size.Split("x")[0]
                            $Script:SqlSchemaWindowForm.Definition.Height = $Size.Split("x")[1]
                            "SqlSchemaWindowForm Height: {0}" -f $Script:SqlSchemaWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                        }
                        $Script:SqlSchemaWindowForm.PositionManager.Synchronizing = $false
                    }, [System.Windows.Threading.DispatcherPriority]::Render)
                $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $true
                $Script:MainWindowForm.Elements.ButtonShowSqlSchema | Set-ButtonContent -Content "Hide Schema"
                $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetTop = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Top)
                "PositionManagerSqlSchemaWindow PositionOffSetLeft: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft | Write-LogOutput -LogType DEBUG
                $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetLeft = [Int]::Abs($Script:MainWindowForm.Definition.Left) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Left)
                "PositionManagerSqlSchemaWindow PositionOffSetTop: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.PositionOffSetTop | Write-LogOutput -LogType DEBUG
                "SqlSchemaWindowForm Position: {0}x{1}, Dimensions: {2}x{3}" -f $Script:SqlSchemaWindowForm.Definition.Left, $Script:SqlSchemaWindowForm.Definition.Top, $Script:SqlSchemaWindowForm.Definition.Width , $Script:SqlSchemaWindowForm.Definition.Height | Write-LogOutput -LogType DEBUG
                $Script:SqlSchemaWindowForm.State = "Open"
            })

        $Script:SqlSchemaWindowForm.Definition.Add_Closing({
                $_ | Show-EventInfo
                Save-WindowMeasurements
                $Script:SqlSchemaWindowForm.State = "Closing"
                if ($Script:MainWindowForm.State -eq "Open") {
                    $false | Invoke-ConfigSetting -Property "SqlSchemaWindowFormOpen"
                }
            })

        $Script:SqlSchemaWindowForm.Definition.Add_Closed({
                $_ | Show-EventInfo
                $Script:SqlSchemaWindowForm.State = "Closed"
                $Script:MainWindowForm.Elements.ButtonShowSqlSchema | Set-ButtonContent -Content "Schema"
            })

        $Script:SqlSchemaWindowForm.Definition.Show()

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Push-ToEditor {
    PARAM(
        [parameter(Mandatory = $true)]
        [string]$ScriptToExecute
    )
    try {
        $OnCompletedScriptBlock = {
            try {
                if ($Script:Task.Status -eq "RanToCompletion") {
                    "Editor value updated!" | Write-LogOutput -LogType DEBUG
                }
                elseif ($Script:Task.Status -eq "Faulted") {
                    "Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                }
                else {
                    "Task result: {0}" -f $Script:Task.Status | Write-LogOutput -LogType DEBUG
                }
            }
            catch {
                $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
            }
        }

        Invoke-ExecuteScriptAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Reset-Application {
    PARAM(
        [switch]$SkipTextBoxURL,
        [switch]$SkipAuthentication,
        [switch]$ResetEditor
    )

    try {
        if ($null -ne $Script:SqlSchemaWindow -and $null -ne $Script:SqlSchemaWindow.Definitions -and $Script:SqlSchemaWindow.Definitions.IsVisible) {
            $Script:SqlSchemaWindow.Definitions.Close()
        }
        $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $False
        $Script:MainWindowForm.Elements.ButtonSaveOutputFile.IsEnabled = $False
        $Script:MainWindowForm.Elements.ButtonOpenOutputFile.IsEnabled = $False

        if (!$SkipTextBoxURL) {
            $Script:MainWindowForm.Elements.TextBoxURL.Text = $null
            $null | Invoke-ConfigSetting -Property "BaseUrl"
            $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.SelectedItem = $Null
            $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Clear()
            $null, $null | Invoke-ConfigSetting -Property "CurrentDataConnection"
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $Null
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Clear()
            $Script:MainWindowForm.Elements.CheckboxMyQueries.IsChecked = $False
            $Script:MainWindowForm.Elements.CheckboxMyQueries.IsEnabled = $False
            $null, $null | Invoke-ConfigSetting -Property "CurrentSqlQuery"
        }
        $Script:MainWindowForm.Elements.TextBoxURL.IsEnabled = $True

        if (!$SkipAuthentication) {
            $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem = $Null
            $null | Invoke-ConfigSetting -Property "LastAuthentication"
            if ($Script:MainWindowForm.Elements.TextBoxUserName.IsEnabled) {
                $Script:MainWindowForm.Elements.TextBoxUserName.Text = $Null
                $Script:MainWindowForm.Elements.TextBoxUserName.IsEnabled = $false
            }
            if ($Script:MainWindowForm.Elements.TextBoxPassword.IsEnabled) {
                $Script:MainWindowForm.Elements.TextBoxPassword.Password = $Null
                $Script:MainWindowForm.Elements.TextBoxPassword.IsEnabled = $false
            }
        }

        if (!$SkipTextBoxURL -and !$SkipAuthentication) {
            $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $False
            $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $null
        }

        $Script:MainWindowForm.Elements.ButtonShowOutput.IsEnabled = $False
        $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $False
        $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $False

        if ($ResetEditor -and $null -ne $Script:Webview.Object.CoreWebView2) {
            Set-EditorValue
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Save-WindowMeasurements {
    try {
        "Save-WindowMeasurements" | Write-LogOutput -LogType VERBOSE2
        $MinDelta = 500
        $Timestamp = Get-Date
        if ($Script:RunTimeConfig.LastWindowMeasured -gt (Get-Date).AddMilliseconds(-$MinDelta)) {
            "WindowMeasurements save ignored because last measurement was less than {0} milliseconds ago. Current Measurement save timestamp = '{1}', last measurement save timestamp: '{2}'" -f $MinDelta, $Timestamp.ToString("o"), $Script:RunTimeConfig.LastWindowMeasured.ToString("o") | Write-LogOutput -LogType VERBOSE2
            return
        }
        "WindowMeasurements Current Measurement save timestamp = '{0}', last measurement save timestamp: '{1}'" -f $Timestamp.ToString("o"), $Script:RunTimeConfig.LastWindowMeasured.ToString("o") | Write-LogOutput -LogType VERBOSE2
        $Script:RunTimeConfig.LastWindowMeasured = Get-Date

        if ($Script:MainWindowForm.Definition.IsVisible) {
            $ValueSize = "{0}x{1}" -f [Int]::Abs(($Script:MainWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Width")), [Int]::Abs(($Script:MainWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Height"))
            $ValueSize | Invoke-ConfigSetting -Property "MainWindowSize"
            $ValuePosition = "{0}x{1}" -f [Int]::Abs(($Script:MainWindowForm.Definition | Get-ValidWindowPosition -Setting "Left")), [Int]::Abs(($Script:MainWindowForm.Definition | Get-ValidWindowPosition -Setting "Top"))
            $ValuePosition | Invoke-ConfigSetting -Property "MainWindowPosition"
            "MainWindowForm Size:'{0}', Position: '{1}'" -f $ValueSize, $ValuePosition | Write-LogOutput -LogType VERBOSE2
            if ($null -ne $Script:LogWindowForm -and $null -ne $Script:LogWindowForm.Definition -and $Script:LogWindowForm.Definition.IsVisible) {
                $ValueSize = "{0}x{1}" -f [Int]::Abs(($Script:LogWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Width")), [Int]::Abs(($Script:LogWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Height"))
                $ValueSize | Invoke-ConfigSetting -Property "LogWindowSize"
                $ValuePosition = "{0}x{1}" -f [Int]::Abs(($Script:LogWindowForm.Definition | Get-ValidWindowPosition -Setting "Left")), [Int]::Abs(($Script:LogWindowForm.Definition | Get-ValidWindowPosition -Setting "Top"))
                $ValuePosition | Invoke-ConfigSetting -Property "LogWindowPosition"
                "LogWindowForm Size:'{0}', Position: '{1}'" -f $ValueSize, $ValuePosition | Write-LogOutput -LogType VERBOSE2
            }
            else {
                "LogWindowForm is not visible" | Write-LogOutput -LogType VERBOSE2
            }
            if ($null -ne $Script:SqlSchemaWindowForm -and $null -ne $Script:SqlSchemaWindowForm.Definition -and $Script:SqlSchemaWindowForm.Definition.IsVisible) {
                $ValueSize = "{0}x{1}" -f [Int]::Abs(($Script:SqlSchemaWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Width")), [Int]::Abs(($Script:SqlSchemaWindowForm.Definition | Get-ValidWindowMeasurement -Setting "Height"))
                $ValueSize | Invoke-ConfigSetting -Property "SqlSchemaWindowSize"
                $ValuePosition = "{0}x{1}" -f [Int]::Abs(($Script:SqlSchemaWindowForm.Definition | Get-ValidWindowPosition -Setting "Left")), [Int]::Abs(($Script:SqlSchemaWindowForm.Definition | Get-ValidWindowPosition -Setting "Top"))
                $ValuePosition | Invoke-ConfigSetting -Property "SqlSchemaWindowPosition"
                "SqlSchemaWindowForm Size:'{0}', Position: '{1}'" -f $ValueSize, $ValuePosition | Write-LogOutput -LogType VERBOSE2
            }
            else {
                "SqlSchemaWindowForm is not visible" | Write-LogOutput -LogType VERBOSE2
            }
        }
        else {
            "MainWindowForm is not visible" | Write-LogOutput -LogType VERBOSE2
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-AuthenticationOption {

    try {
        if ($Null -ne $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content) {

            switch ($Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content) {
                { $_ -in @("Basic", "Windows", "OAuth" ) } {

                    if ($_ -eq "OAuth") {
                        $Script:MainWindowForm.Elements.LabelUserName | Set-LabelContent-Content "Client ID:"
                        $Script:MainWindowForm.Elements.LabelPassword | Set-LabelContent-Content "Client Secret:"
                    }
                    else {
                        $Script:MainWindowForm.Elements.LabelUserName | Set-LabelContent-Content "Username:"
                        $Script:MainWindowForm.Elements.LabelPassword | Set-LabelContent-Content "Password:"
                    }
                    $Script:MainWindowForm.Elements.LabelUserName.Visibility = "Visible"
                    $Script:MainWindowForm.Elements.LabelPassword.Visibility = "Visible"
                    $Script:MainWindowForm.Elements.TextBoxUserName.Visibility = "Visible"
                    $Script:MainWindowForm.Elements.TextBoxPassword.Visibility = "Visible"
                    $Script:MainWindowForm.Elements.TextBoxUserName.IsEnabled = $True
                    $Script:MainWindowForm.Elements.TextBoxPassword.IsEnabled = $True
                    if (!$Script:RunTimeData.RestMethodParam.ContainsKey("Credential")) {
                        $Script:RunTimeData.RestMethodParam.Add("Credential", $Null)
                    }
                }

                default {
                    $Script:MainWindowForm.Elements.TextBoxUserName.IsEnabled = $False
                    $Script:MainWindowForm.Elements.TextBoxPassword.IsEnabled = $False
                    $Script:MainWindowForm.Elements.LabelUserName.Visibility = "Hidden"
                    $Script:MainWindowForm.Elements.LabelPassword.Visibility = "Hidden"
                    $Script:MainWindowForm.Elements.TextBoxUserName.Visibility = "Hidden"
                    $Script:MainWindowForm.Elements.TextBoxPassword.Visibility = "Hidden"
                    $Script:MainWindowForm.Elements.TextBoxUserName | Set-TextBlockText -Text $null
                    $Script:MainWindowForm.Elements.TextBoxPassword.Password = ""
                    $Null | Invoke-ConfigSetting -Property "UserName"
                    if ($Script:RunTimeData.RestMethodParam.ContainsKey("Credential")) {
                        $Script:RunTimeData.RestMethodParam.Remove("Credential")
                    }
                }
            }
            $Script:RunTimeConfig.AuthenticationSet = $True
            $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content | Invoke-ConfigSetting -Property "LastAuthentication"
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }

}
function Set-ButtonContent {
    PARAM(
        [Parameter(Mandatory = $true,ValueFromPipeline = $true)]
        $ButtonObject,
        [Parameter(Mandatory = $true)]
        [string]$Content
    )

    try {
        $CurrentButtonContent = $ButtonObject.Content
        $ButtonObject.Content = $Content
        "{0} set from '{1}' to '{2}'" -f $ButtonObject.Name, $CurrentButtonContent, $ButtonObject.Content | Write-LogOutput -LogType DEBUG

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }


}
function Set-ConfigProperty {
    if ($_.Name -notin $CurrentPoperties.Name) {
        $Value = $Null

        if ($_.Type -eq "Bool") {
            $Value = $false
        }
        elseif ($_.Type -eq "Int") {
            $Value = -1
        }
        elseif ($_.Type -eq "String") {
            $Value = $null
        }
        elseif ($_.Type -eq "PSObject") {
            $Value = [pscustomobject]@{}
            $_.Attributes | ForEach-Object {
                if ($_.Type -eq "Bool") {
                    $Value | Add-Member -MemberType NoteProperty -Name $_.Name -Value $false
                }
                elseif ($_.Type -eq "Int") {
                    $Value | Add-Member -MemberType NoteProperty -Name $_.Name -Value -1
                }
                elseif ($_.Type -eq "String") {
                    $Value | Add-Member -MemberType NoteProperty -Name $_.Name -Value $null
                }
                if ($_.DefaultValue) {
                    $Value.$($_.Name) = $_.DefaultValue
                }
            }
        }
        if ($_.DefaultValue) {
            $Value = $_.DefaultValue
        }
        $Config | Add-Member -MemberType NoteProperty -Name $_.Name -Value $Value
    }
}
function Set-DataConnection {
    try {


        if (!$Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items.Contains($Script:AppConfig.CurrentDataConnection.FullName)) {
            $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items.Add($Script:AppConfig.CurrentDataConnection.FullName) | Out-Null
        }
        $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.SelectedValue = $Script:AppConfig.CurrentDataConnection.FullName
        $Script:MainWindowForm.Elements.TextBlockDatabaseName.Text = $Script:AppConfig.CurrentDataConnection.DisplayName
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-EditorBackground {

    try {

        $OnCompletedScriptBlock = {
            try {
                if (!$Script:Task.Status -eq "RanToCompletion") {
                    "Monaco Editor Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                }
                else{
                    "Monaco Editor Task completed successfully." | Write-LogOutput -LogType DEBUG
                }
            }
            catch {
                $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
            }
        }
        $ScriptToExecute = "container.style.backgroundImage = url('`${0}');" -f (Get-Icon -Type Base64)
        Invoke-ExecuteScriptAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
        $ScriptToExecute = "container.style.backgroundSize = `"200px 200px`";"
        Invoke-ExecuteScriptAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
        $ScriptToExecute = "container.style.backgroundPosition = `"center`";"
        Invoke-ExecuteScriptAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock
        $ScriptToExecute = "container.style.backgroundRepeat = `"no-repeat`";"
        Invoke-ExecuteScriptAsync -ScriptToExecute $ScriptToExecute -OnCompletedScriptBlock $OnCompletedScriptBlock

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-EditorValue {
    try {
        if ($null -ne $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem) {
            "Selected SQL Query object: {0}" -f $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem.Content | Write-LogOutput -LogType DEBUG
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem.Content | Invoke-ConfigSetting -Property "CurrentSqlQuery"

            if ([string]::IsNullOrWhiteSpace($Script:AppConfig.CurrentSqlQuery.DoId)) {
                "Omada Url not set or Query not selected. Set correct values to execute queries!" | Write-LogOutput -LogType WARNING
                return
            }
            if (!(Test-ConnectionRequirements)) {
                "Connection requirements are not met" | Write-LogOutput -LogType DEBUG
                return
            }

            $Private:Result = Get-SqlQueryObject
            if ($null -ne $Private:Result) {

                $Script:RunTimeData.CurrentSqlQuery.DoId = $Private:Result.Id
                $Script:RunTimeData.CurrentSqlQuery.DisplayName = $Private:Result.DisplayName
                $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $Private:Result.DisplayName
                $Private:Result.C_SQLTROUBLESHOOTING_DATACONNECTION.Id, $Private:Result.C_SQLTROUBLESHOOTING_DATACONNECTION.DisplayName | Invoke-ConfigSetting -Property "CurrentDataConnection"

                Set-DataConnection

                $Script:MainWindowForm.Elements.ButtonExecuteQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonSaveQuery.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonReset.IsEnabled = $True
                $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $True
                $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $true

                if ($null -ne $Script:Webview.Object.CoreWebView2) {

                    $ScriptToExecute = "editor.setValue('{0}');" -f ($Private:Result.C_QUERY -replace "`n", "\n" -replace "`r", "\r" -replace "`t", "\t" -replace "'", "\'")
                    Push-ToEditor -ScriptToExecute $ScriptToExecute
                    $Script:RunTimeData.CurrentQueryText = $Private:Result.C_QUERY
                    "Query {0} retrieved!" -f $Script:AppConfig.CurrentSqlQuery.DoId | Write-LogOutput
                }
            }
        }
        else {
            "Clear Editor Value because no query is selected!" | Write-LogOutput -LogType DEBUG
            $ScriptToExecute = "editor.setValue('');"
            Push-ToEditor -ScriptToExecute $ScriptToExecute
            Reset-Application -SkipTextBoxURL -SkipAuthentication
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-LabelContent {
    PARAM(
        [Parameter(Mandatory = $true,ValueFromPipeline = $true)]
        $LabelObject,
        [Parameter(Mandatory = $true)]
        [string]$Content
    )

    try {
        $CurrentButtonContent = $LabelObject.Content
        $LabelObject.Content = $Content
        "{0} set from '{1}' to '{2}'" -f $LabelObject.Name, $CurrentButtonContent, $LabelObject.Content | Write-LogOutput -LogType DEBUG

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }


}
function Set-MonacoSchema {
    PARAM(
        $ReturnValue
    )
    try {
        "Add schema to Monaco editor." | Write-LogOutput -LogType DEBUG
        $TableObjects = @()
        foreach ($Table in ($ReturnValue.d | Get-Member -MemberType NoteProperty)) {
            $TableName = $($Table.Name).Split(".")[1]
            $TableObject = [pscustomobject]@{
                $TableName = @()
            }
            foreach ($Column in $ReturnValue.d.$($Table.Name)) {
                $TableObject.$TableName += $Column.Split(" ")[0]
            }
            $TableObjects += $TableObject
        }
        $TableObjectsJson = $TableObjects | ConvertTo-Json -Depth 5

        "Schema for Monaco editor." | Write-LogOutput -LogType VERBOSE
        $OnCompletedScriptBlock = {
            try {
                if (!$Script:Task.Status -eq "RanToCompletion") {
                    "Monaco Editor Task failed: {0}" -f $Script:Task.Status | Write-LogOutput -LogType ERROR
                }
                else{
                    "Monaco Editor Task completed successfully." | Write-LogOutput -LogType DEBUG
                }
            }
            catch {
                $Script:Task.Exception.Message | Write-LogOutput -LogType ERROR
            }
        }

        "Push schema to Monaco editor." | Write-LogOutput -LogType DEBUG
        Invoke-ExecuteScriptAsync -ScriptToExecute "setSchema($TableObjectsJson);" -OnCompletedScriptBlock $OnCompletedScriptBlock

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-OmadaUrl {

    try {

        if (![string]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxURL.Text)) {

            if ($Script:MainWindowForm.Elements.TextBoxURL.Text -notlike "http*") {
                if ($Script:MainWindowForm.Elements.TextBoxURL.Text -notlike "*.*" -and $Script:MainWindowForm.Elements.TextBoxURL.Text -notlike "*.omada.cloud") {
                    $Script:MainWindowForm.Elements.TextBoxURL | Set-TextBlockText -Text "https://$($Script:MainWindowForm.Elements.TextBoxURL.Text).omada.cloud"
                }
                else {
                    $Script:MainWindowForm.Elements.TextBoxURL | Set-TextBlockText -Text "https://$($Script:MainWindowForm.Elements.TextBoxURL.Text)"
                }
            }

            $Uri = [System.Uri]::new($Script:MainWindowForm.Elements.TextBoxURL.Text.Trim())

            if ($Uri.IsAbsoluteUri -and ($Uri.Scheme -eq 'http' -or $Uri.Scheme -eq 'https')) {
("Input Url {0} is valid." -f $Uri.IsAbsoluteUri) | Write-LogOutput -LogType DEBUG
            }
            else {
                $Null | Invoke-ConfigSetting -Property "BaseUrl"
                $Script:MainWindowForm.Elements.TextBoxURL.Text = $Null
                "Input Url {0} is not valid." -f $Script:MainWindowForm.Elements.TextBoxURL.Text.Trim() | Write-LogOutput -LogType ERROR
                return
            }

            try {
                $DnsResult = Resolve-DnsName -Name $Uri.Host -QuickTimeout -ErrorAction SilentlyContinue
                if (($DnsResult | Measure-Object).Count -le 0) {
                    "DNS resolution for {0} failed!" -f $Uri.Host | Write-LogOutput -LogType ERROR
                    return
                }
            }
            catch {
                $Null | Invoke-ConfigSetting -Property "BaseUrl"
                $Script:MainWindowForm.Elements.TextBoxURL.Text = $Null
                $Script:MainWindowForm.Elements.TextBlockUrl.Text = $Null
                "Endpoint {0} not found!" -f $Uri.AbsoluteUri | Write-LogOutput -LogType ERROR
            }

            $Uri.AbsoluteUri.TrimEnd("/") | Invoke-ConfigSetting -Property "BaseUrl"

            if ($Script:CurrentUrl -ne $Script:AppConfig.BaseUrl) {
                "Omada Url set to: {0}" -f $Script:AppConfig.BaseUrl | Write-LogOutput -LogType DEBUG
                $Script:CurrentUrl = $Script:AppConfig.BaseUrl
                if ($Script:RunTimeConfig.AuthenticationSet) {
                    "Authentication is set, force update query list!" | Write-LogOutput -LogType DEBUG
                    Update-QueryList -ForceRefresh
                }
            }
            elseif([string]::IsNullOrEmpty($Script:AppConfig.BaseUrl)) {
                "Omada Url is empty!" | Write-LogOutput -LogType DEBUG
            }
            else{
                "Omada Url maintained: {0}" -f $Script:AppConfig.BaseUrl | Write-LogOutput -LogType DEBUG
            }
        }
        else {
            Reset-Application
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-TextBlockText {
    PARAM(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $TextBlockObject,
        [Parameter(Mandatory = $false)]
        [string]$Text
    )

    try {
        $CurrentButtonContent = $TextBlockObject.Text
        if ([string]::IsNullOrEmpty($Text)) {
            $TextBlockObject.Text = $null
        }
        else {
            $TextBlockObject.Text = $Text
        }
        $TextBlockObject.Text = $Text
        "{0} set from '{1}' to '{2}'" -f $TextBlockObject.Name, $CurrentButtonContent, $TextBlockObject.Text | Write-LogOutput -LogType DEBUG

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }


}
function Set-TextBoxWrapping {
    PARAM(
        $TextBox,
        [bool]$Wrap =$false
    )
    try {
        "Set TextBox wrapping to {0}" -f $Wrap | Write-LogOutput -LogType DEBUG
        if ($Wrap) {
            $TextBox.TextWrapping = "WrapWithOverflow"
        }
        else {
            $TextBox.TextWrapping = "NoWrap"
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-WindowPosition {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [parameter(Mandatory = $true)]
        [string]$Setting
    )
    try {
        $Form.Left | Write-Host -ForegroundColor DarkYellow
        $Form.Top | Write-Host -ForegroundColor DarkYellow

        $Form.Left = [Int]::Abs($Setting.Split("x")[0])
        $Form.Top = [Int]::Abs($Setting.Split("x")[1])
        $Form.Left | Write-Host -ForegroundColor Yellow
        $Form.Top | Write-Host -ForegroundColor Yellow

        "{0} position setting {1}: {2}x{3}" -f $Form.Name, $Setting, $Form.Left, $Form.Top | Write-LogOutput -LogType VERBOSE2

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Set-WindowSize {
    PARAM(
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $Form,
        [parameter(Mandatory = $true)]
        [string]$Setting
    )
    try {
        $Form.Width = [Int]::Abs($Setting.Split("x")[0])
        $Form.Height = [Int]::Abs($Setting.Split("x")[1])

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Show-EventInfo {
    PARAM(
        [parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
        $Item,
        [validateSet("DEBUG", "VERBOSE", "VERBOSE2")]
        $LogType = "DEBUG"
    )
    try {
        $CallStack = Get-PSCallStack
        if ($Item -is [Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs]) {
            "Webview success: '{0}' Source: '{1}'" -f $Item.IsSuccess, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
        elseif ($Item -is [System.Windows.Window]) {
            "Form: '{0}', Event: '{1}', Event Type: '{2}', Source: '{3}'" -f $Item.Source.Title, $Item.RoutedEvent.Name, $Item.RoutedEvent.OwnerType.FullName, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
        elseif ($Item -is [System.Windows.Controls.SelectionChangedEventArgs]) {
            "Control: '{0}', Event: '{1}', Event Type: '{2}', Added values: {3}, Removed values: {4}, Source: '{5}'" -f $Item.Source.Name, $Item.RoutedEvent.Name, $Item.RoutedEvent.OwnerType.FullName, ($Item.AddedItems | Measure-Object).Count, ($Item.RemovedItems | Measure-Object).Count, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
        elseif ($Item -is [System.Windows.SizeChangedEventArgs]) {
            "Control: '{0}', Event: '{1}', Event Type: '{2}', PreviousSize: {3}, NewSize: {4}, Source: {5}" -f $Item.Source.Name, $Item.RoutedEvent.Name, $Item.RoutedEvent.OwnerType.FullName, $Item.PreviousSize, $Item.NewSize, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
        elseif ($Item -is [System.Windows.RoutedEventArgs]) {
            "Event: '{0}', Event Type: '{1}, Source: '{2}'" -f $Item.RoutedEvent.Name, $Item.RoutedEvent.OwnerType.FullName, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
        elseif ($Item -is [System.EventArgs]) {
            if ([string]::IsNullOrWhiteSpace($Item.RoutedEvent.Name)) {
                "Event: '{0}', Source: '{1}'" -f $Item, $CallStack[1].Location | Write-LogOutput -LogType $LogType
            }
            else {
                "Event: '{0}', Source: '{1}'" -f $Item.RoutedEvent.Name, $CallStack[1].Location | Write-LogOutput -LogType $LogType
            }
        }
        else {
            "Control: {0}, Event: '{1}', Event Type: '{2}', Source: '{3}'" -f $Item.Source.Name, $Item.RoutedEvent.Name, $Item.RoutedEvent.OwnerType.FullName, $CallStack[1].Location | Write-LogOutput -LogType $LogType
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Show-PopupWindow {
    PARAM(
        $Message
    )
    try {

        if($null -eq $Script:MainWindowForm -or $null -eq $Script:MainWindowForm.Definition -or !$Script:MainWindowForm.Definition.IsVisible) {
            return
        }

        $PopupWindow = New-Object System.Windows.Window
        $PopupWindow.WindowStyle = [System.Windows.WindowStyle]::None
        $PopupWindow.ResizeMode = [System.Windows.ResizeMode]::NoResize
        $PopupWindow.Width = 200
        $PopupWindow.Height = 50
        $PopupWindow.Background = [System.Windows.Media.Brushes]::White
        $PopupWindow.AllowsTransparency = $true
        $PopupWindow.Opacity = 0.8
        $PopupWindow.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterOwner
        $PopupWindow.Owner = $Script:MainWindowForm.Definition
        $PopupWindow.ShowInTaskbar = $false

        $Grid = New-Object System.Windows.Controls.Grid
        $Grid.Margin = '0'

        $PopupWindowBorder = New-Object System.Windows.Controls.Border
        $PopupWindowBorder.Background = [System.Windows.Media.Brushes]::Purple
        $PopupWindowBorder.CornerRadius = '5'
        $PopupWindowBorder.Padding = '5'


        $PopupWindowInsideBorder = New-Object System.Windows.Controls.Border
        $PopupWindowInsideBorder.Background = [System.Windows.Media.Brushes]::LightGray
        $PopupWindowInsideBorder.CornerRadius = '5'
        $PopupWindowInsideBorder.Padding = '5'


        $PopupWindowLabel = New-Object System.Windows.Controls.Label
        $PopupWindowLabel.Content = $Message
        $PopupWindowLabel.FontFamily = "Segoe UI"
        $PopupWindowLabel.FontSize = 12

        $PopupWindowLabel.FontWeight = "Bold"
        $PopupWindowLabel.HorizontalContentAlignment = "Center"
        $PopupWindowLabel.VerticalContentAlignment = "Center"
        $PopupWindowLabel.Foreground = [System.Windows.Media.Brushes]::Black

        $PopupWindowInsideBorder.Child = $PopupWindowLabel
        $PopupWindowBorder.Child = $PopupWindowInsideBorder
        $Grid.Children.Add($PopupWindowBorder) | Out-Null
        $PopupWindow.Content = $Grid

        $PopupWindow.Show() | Out-Null
        return $PopupWindow
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Test-ConnectionRequirements {

    try {

        if ([string]::IsNullOrEmpty($Script:MainWindowForm.Elements.TextBoxURL.Text)) {
            "URL is empty" | Write-LogOutput -LogType DEBUG
            return $false
        }
        if ($null -eq $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem) {
            "Authentication option is not selected" | Write-LogOutput -LogType DEBUG
            return $false
        }
        if ($Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content -eq "OAuth") {
            "OAuth is selected" | Write-LogOutput -LogType DEBUG
            if ([string]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxUserName.Text)) {
                "Username is empty" | Write-LogOutput -LogType DEBUG
                return $false
            }
            if ([string]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxPassword.Password)) {
                "Password is empty" | Write-LogOutput -LogType DEBUG
                return $false
            }
            "OAuth connection requirements are met" | Write-LogOutput -LogType DEBUG
            return $true
        }
        "Browser connection requirements are met" | Write-LogOutput -LogType DEBUG
        return $true
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Test-ConnectionSettings {

    try {
        if ([string]::IsNullOrEmpty($Script:MainWindowForm.Elements.TextBoxURL.Text) -or $null -eq $Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem) {
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.IsEnabled = $False
            $Script:MainWindowForm.Elements.ButtonRefreshQueries.IsEnabled = $False
            $Script:MainWindowForm.Elements.ButtonNewQuery.IsEnabled = $False
            $Script:MainWindowForm.Elements.TextBlockConnectionStatus | Set-TextBlockText -Text "Disconnected"
            $Script:MainWindowForm.Elements.TextBlockUrl | Set-TextBlockText -Text "-"
            $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $False
            $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $null
        }
        else {
            if ($Script:MainWindowForm.Elements.ComboBoxSelectAuthenticationOption.SelectedItem.Content -eq "OAuth" -and
([string]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxUserName.Text) -or [string]::IsNullOrWhiteSpace($Script:MainWindowForm.Elements.TextBoxPassword.Password))) {
                $Script:MainWindowForm.Elements.ButtonReset.IsEnabled = $True
                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.IsEnabled = $False
                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $Null
                $Script:MainWindowForm.Elements.CheckboxMyQueries.IsEnabled = $False
                $Script:MainWindowForm.Elements.ButtonRefreshQueries.IsEnabled = $False
                $Script:MainWindowForm.Elements.ButtonNewQuery.IsEnabled = $False
                $Script:MainWindowForm.Elements.TextBlockConnectionStatus | Set-TextBlockText -Text "Disconnected"
                $Script:MainWindowForm.Elements.TextBlockUrl | Set-TextBlockText -Text "-"
                $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $False
                $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $null
            }
            else {
                $Script:MainWindowForm.Elements.ButtonReset.IsEnabled = $True
                $Script:MainWindowForm.Elements.ComboBoxSelectQuery.IsEnabled = $true
                $Script:MainWindowForm.Elements.CheckboxMyQueries.IsEnabled = $true
                $Script:MainWindowForm.Elements.ButtonRefreshQueries.IsEnabled = $true
                $Script:MainWindowForm.Elements.ButtonNewQuery.IsEnabled = $true
                $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $true
                $Script:MainWindowForm.Elements.TextBlockConnectionStatus | Set-TextBlockText -Text "Connected"
                $Script:MainWindowForm.Elements.TextBlockUrl.Text = ([System.Uri]::new($Script:MainWindowForm.Elements.TextBoxUrl.Text)).Authority

                if (($Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items | Measure-Object).Count -le 1 -or ($Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items | Measure-Object).Count -le 1) {
                    if ($null -ne $Script:MainWindowForm -and $Script:MainWindowForm.Definition -and $Script:MainWindowForm.Definition.IsVisible) {
                        $ConnectingWindow = Show-PopupWindow -Message "Connecting to Omada..."
                    }
                    if (($Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items | Measure-Object).Count -le 1) {
                        Update-DataConnectionList -NotShowPopupWindow
                    }
                    if (($Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items | Measure-Object).Count -le 1) {
                        Update-QueryList -NotShowPopupWindow
                    }
                    if ($null -ne $ConnectingWindow) {
                        $ConnectingWindow.Close()
                    }
                }
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Test-LogWindowOpen {

    try {
        if ($null -ne $Script:LogWindowForm -and $null -ne $Script:LogWindowForm.Definition -and $Script:LogWindowForm.Definition.IsVisible) {
            "Test-LogWindowOpen: true" | Write-LogOutput -LogType VERBOSE2
            return $true
        }
        else {
            "Test-LogWindowOpen: false" | Write-LogOutput -LogType VERBOSE2
            return $false
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Test-MainWindowOpen {

    try {
        if ($null -ne $Script:MainWindowForm -and $null -ne $Script:MainWindowForm.Definition -and $Script:MainWindowForm.Definition.IsVisible) {
            return $true
        }
        else {
            return $false
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Test-Shortcut {
    $LocalAppDataPath = Join-Path ([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::LocalApplicationData)) -ChildPath "OmadaSqlTroubleShooter"
    if (-not (Test-Path -Path $LocalAppDataPath)) {
        New-Item -Path $LocalAppDataPath -ItemType Directory -Force | Out-Null
    }
    $PsCallStack = Get-PSCallStack | Where-Object { $_.ScriptName -like "*OmadaSqlTroubleShooter.psm1" }

    $ModulePath = Split-Path -Path $PsCallStack.ScriptName -Parent
    [xml]$MainWindowXaml = Get-Content (Join-Path $ModulePath -ChildPath "lib\ui\MainWindow.xaml")
    $ScriptTitle = $MainWindowXaml.Window.Title
    $WshShell = New-Object -ComObject WScript.Shell
    $ShortcutFullPath = Join-Path $WshShell.SpecialFolders("Programs") -ChildPath ("{0}.lnk" -f $ScriptTitle)

    $RunPath = Join-Path $LocalAppDataPath -ChildPath "Run.ps1"

    if (-not (Test-Path $ShortcutFullPath -PathType Leaf) ) {
        "Start Menu shortcut for this application is not present. Run Set-OmadaSqlTroubleshooterShortcut to create a Start Menu shortcut" | Write-Warning
    }
    else {
        if (-not (Test-Path $RunPath -PathType Leaf) ) {
            "Run.ps1. Start Menu shortcut will not work. Run Set-OmadaSqlTroubleshooterShortcut to fix the shortcut(s)." | Write-Error
        }
    }
}
function Test-SqlSchemaWindowOpen {

    try {
        if ($null -ne $Script:SqlSchemaWindowForm -and $null -ne $Script:SqlSchemaWindowForm.Definition -and $Script:SqlSchemaWindowForm.Definition.IsVisible) {
            "Test-SqlSchemaWindowOpen: true" | Write-LogOutput -LogType VERBOSE2
            return $true
        }
        else {
            "Test-SqlSchemaWindowOpen: false" | Write-LogOutput -LogType VERBOSE2
            return $false
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}

function Test-Variable {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'ExcludeVariable', Justification = 'The variable is used, but script analyzer does not recognize it')]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'ExcludeAttribute', Justification = 'The variable is used, but script analyzer does not recognize it')]
    param (
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]$Expression,
        [switch]$ExcludeVariable,
        [switch]$ExcludeAttribute
    )

    function ReturnObject {
        if ($ExcludeVariable -and $ExcludeAttribute) {
            $Return = $false
        }
        elseif ($ExcludeAttribute -and !$ExcludeVariable) {
            $Return.Remove("AttributeExists")
            $Return = $Return.VariableExists
        }
        elseif ($ExcludeVariable -and !$ExcludeAttribute) {
            $Return.Remove("VariableExists")
            $Return = $Return.AttributeExists
        }
        return $Return
    }

    $Parts = $Expression.TrimStart('$').Trim() -split '\.'

    $Root = $Parts[0]

    $ScopePrefix = ''
    if ($Root -match '^(\w+:)') {
        $ScopePrefix = $Matches[1]
        $Root = $Root.Substring($ScopePrefix.Length)
    }

    $SessionState = $ExecutionContext.SessionState
    $Variable = $SessionState.PSVariable.Get($Root)

    $Return = @{
        VariableExists  = $false
        AttributeExists = $false
    }

    if ($null -eq $Variable) {
        $Return.VariableExists = $false
        return ReturnObject
    }

    $CurrentObject = $Variable.Value
    if (($Parts | Measure-Object).Count -eq 1) {
        return ReturnObject
    }
    foreach ($Part in $Parts[1..($Parts.Count - 1)]) {
        if ($null -eq $CurrentObject) {
            $Return.VariableExists = $true
            return ReturnObject
        }

        if ($CurrentObject -is [hashtable]) {
            $Member = $CurrentObject.keys | Where-Object {$_ -eq $Part}
        }
        else {
            $Member = $CurrentObject | Get-Member  -Name $Part -Force -ErrorAction SilentlyContinue | Where-Object {$_.MemberType -in @("Property", "Field", "Method")}
        }

        if ($null -eq $Member) {
            $Return.VariableExists = $true
            return ReturnObject
        }
        $CurrentObject = $CurrentObject.$Part
    }
    return ReturnObject
}
function Update-DataConnectionList {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'SetInitialConnection', Justification = 'The variable is used, but script analyzer does not recognize it')]
    PARAM(
        [switch]$NotShowPopupWindow
    )

    try {

        if (!(Test-ConnectionRequirements)) {
            "Connection not ready" | Write-LogOutput -LogType DEBUG
            return
        }

        "Retrieve data connections" | Write-LogOutput -LogType DEBUG
        $SqlQueryViewContents = Get-SqlTroubleShooterView
        if ($null -ne $SqlQueryViewContents) {
            $Script:RunTimeData.RestMethodParam.Uri = "{0}/dataobjdlg.aspx?DOID={1}" -f $Script:AppConfig.BaseUrl, $SqlQueryViewContents[0].$($Script:RunTimeData.DataobjdlgAspxAttributeMapping.SqlQueryDoId)
            $Script:RunTimeData.RestMethodParam.Body = $null
            $Script:RunTimeData.RestMethodParam.Method = "GET"
            $Private:Result = Invoke-OmadaPSWebRequestWrapper

            if ($null -eq $Private:Result) {
                "Failed to retrieve data connections! Data connection cannot be changed!" | Write-LogOutput -LogType WARNING
                $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.IsEnabled = $False
                $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $false
            }
            else {
                if (!$NotShowPopupWindow) {
                    $UpdateDataConnectionsWindow = Show-PopupWindow -Message "Updating Data Connections..."
                }

                $SelectedDataConnection = $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.SelectedItem.Content
                "Stored current selected data connection (if not empty): {0}" -f $SelectedDataConnection | Write-LogOutput -LogType DEBUG
                $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items.Clear()

                if ($null -ne $Private:Result) {


                    $SetInitialConnection = $true
                    $Private:Result -split "`r`n" | ForEach-Object {
                        $Options = [regex]::Matches($Private:Result, '<option.*?value="(\d+).*?data-uid="(.*?)".*?>(.*?)</option>')
                        foreach ($Match in $Options) {
                            $DataConnectionDisplayName = "{0} - {1}" -f $Match.Groups[3].Value, $Match.Groups[1].Value
                            if ($DataConnectionDisplayName -notin $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items.Content) {
                                "Add data connection {0}" -f $DataConnectionDisplayName | Write-LogOutput -LogType DEBUG
                                $ComboBoxDataConnectionItem = New-Object System.Windows.Controls.ComboBoxItem
                                $ComboBoxDataConnectionItem.Content = $DataConnectionDisplayName
                                $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items.Add($ComboBoxDataConnectionItem) | Out-Null
                                if ($null -ne $SelectedDataConnection -and $SelectedDataConnection -eq $DataConnectionDisplayName) {
                                    "Set connection {0} as selected data connection" -f $DataConnectionDisplayName | Write-LogOutput -LogType DEBUG
                                    $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.SelectedItem = $ComboBoxDataConnectionItem
                                    $SetInitialConnection = $false
                                }
                            }
                        }
                    }
                    if ($SetInitialConnection) {
                        "Set initial data connection to OISES" | Write-LogOutput -LogType DEBUG
                        $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.SelectedItem = $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items | Where-Object {$_.Content -like "OISES -*"}
                    }
                    $Script:MainWindowForm.Elements.TextBoxDisplayName.IsEnabled = $true
                    $Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.IsEnabled = $True
                    $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $true
                }
                "{0} data connections processed!" -f ($Script:MainWindowForm.Elements.ComboBoxSelectDataConnection.Items | Measure-Object).Count | Write-LogOutput

                if ($null -ne $UpdateDataConnectionsWindow) {
                    $UpdateDataConnectionsWindow.Close()
                }
            }
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Update-LogWindow {

    try {
        if ($null -ne $Script:TextBoxLog) {
            $Script:TextBoxLog.Dispatcher.Invoke({
                    $Script:TextBoxLog.AppendText($LogMessage.Text + "`n")
                    if ($Script:TextBoxLog.IsLoaded -and (Invoke-LogWindowScrollToEnd)) {
                        $Script:TextBoxLog.ScrollToEnd()
                    }
                })
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Update-LogWindowPosition {

    try {
        $Script:LogWindowForm.PositionManager.MainWindowRight = [Int]::Abs($Script:MainWindowForm.Definition.Left) + [Int]::Abs($Script:MainWindowForm.Definition.Width)
        "PositionManagerLogWindow MainWindowRight: {0}" -f $Script:LogWindowForm.PositionManager.MainWindowRight | Write-LogOutput -LogType DEBUG
        $Script:LogWindowForm.PositionManager.MainWindowBottom = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:MainWindowForm.Definition.Height)
        "PositionManagerLogWindow MainWindowBottom: {0}" -f $Script:LogWindowForm.PositionManager.MainWindowRight | Write-LogOutput -LogType DEBUG
        $Script:LogWindowForm.PositionManager.ChildWindowRight = [Int]::Abs($Script:LogWindowForm.Definition.Left) + [Int]::Abs($Script:LogWindowForm.Definition.Width)
        "PositionManagerLogWindow ChildWindowRight: {0}" -f $Script:LogWindowForm.PositionManager.ChildWindowRight | Write-LogOutput -LogType DEBUG
        $Script:LogWindowForm.PositionManager.ChildWindowBottom = [Int]::Abs($Script:LogWindowForm.Definition.Top) - [Int]::Abs($Script:LogWindowForm.Definition.Height)
        "PositionManagerLogWindow ChildWindowBottom: {0}" -f $Script:LogWindowForm.PositionManager.ChildWindowBottom | Write-LogOutput -LogType DEBUG

        if ([Int]::Abs($Script:LogWindowForm.Definition.Left) -lt [Int]::Abs($Script:MainWindowForm.Definition.Left)) {
            $Script:LogWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) + [Int]::Abs($Script:MainWindowForm.Definition.Width)
            "LogWindowForm Definition Left: {0}" -f $Script:LogWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG

        }
        elseif ($Script:LogWindowForm.PositionManager.ChildWindowRight -gt $Script:LogWindowForm.PositionManager.MainWindowRight) {
            $Script:LogWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) - $Script:LogWindowForm.Definition.Width
            "LogWindowForm Definition Left: {0}" -f $Script:LogWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG
        }

        if ($Script:LogWindowForm.Definition.Top -lt [Int]::Abs($Script:MainWindowForm.Definition.Top)) {
            $Script:LogWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top) + [Int]::Abs($Script:MainWindowForm.Definition.Height)
            "LogWindowForm Definition Top: {0}" -f $Script:LogWindowForm.Definition.Top | Write-LogOutput -LogType DEBUG
        }
        elseif ($Script:PositionManager.ChildWindowBottom -gt $MainWindowBottom) {
            $Script:LogWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:LogWindowForm.Definition.Height)
            "LogWindowForm Definition Top: {0}" -f $Script:LogWindowForm.Definition.Top | Write-LogOutput -LogType DEBUG
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Update-QueryList {
    PARAM(
        [switch]$ForceRefresh,
        [switch]$NotShowPopupWindow
    )

    try {
        if (!(Test-ConnectionRequirements)) {
            "Connection not ready" | Write-LogOutput -LogType DEBUG
            return
        }

        $CurrentTimestamp = Get-Date

        if (($Script:RunTimeData.QueryListCache.QueryList | Measure-Object).Count -eq 0 -or $ForceRefresh -or $Script:RunTimeData.QueryListCache.LastRefresh -lt $CurrentTimestamp.AddSeconds( - $($Script:RunTimeData.QueryListCache.TTL))) {
            $Script:RunTimeData.QueryListCache.QueryList = $null
            "Cleared query cache!" | Write-LogOutput -LogType DEBUG
        }

        "Queries in cache: {0}" -f ($Script:RunTimeData.QueryListCache.QueryList | Measure-Object).Count | Write-LogOutput -LogType DEBUG

        if (($Script:RunTimeData.QueryListCache.QueryList | Measure-Object).Count -le 0) {
            if (!$NotShowPopupWindow) {
                $Script:PopUpWindowQueryRefresh = Show-PopupWindow -Message "Refreshing queries..."
            }
            $Script:RunTimeData.QueryListCache.QueryList = @()
            if ($Script:AppConfig.MyQueriesOnly -and ![string]::IsNullOrWhiteSpace($Script:AppConfig.IdentityUserName)) {
                $SqlQueryViewContents = Get-SqlTroubleShooterView | Where-Object { $_.$($Script:RunTimeData.DataobjdlgAspxAttributeMapping.SqlQueryCreatedBy) -eq $Script:AppConfig.IdentityUserName -or $_.$($Script:RunTimeData.DataobjdlgAspxAttributeMapping.SqlQueryChangedBy) -eq $Script:AppConfig.IdentityUserName }
            }

            $Script:RunTimeData.RestMethodParam.Uri = '{0}/odata/dataobjects/C_P_SQLTROUBLESHOOTING?$filter=Deleted ne true and NAME ne ''''' -f $Script:AppConfig.BaseUrl
            "QueryUrl: {0}" -f $Script:RunTimeData.RestMethodParam.Uri | Write-LogOutput -LogType DEBUG
            "Refresh queries started" | Write-LogOutput
            $Script:RunTimeData.RestMethodParam.Body = $Null
            $Script:RunTimeData.RestMethodParam.Method = "GET"
            $Script:RunTimeData.RestMethodParam.Body = $null
            $Private:Result = Invoke-OmadaPSWebRequestWrapper

            $SelectedQuery = $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem.Content
            "Stored current selected query (if not empty): {0}" -f $SelectedQuery | Write-LogOutput -LogType DEBUG
            $SelectedQueryDisplayName = $Script:MainWindowForm.Elements.TextBoxDisplayName.Text
            "Stored current selected query display name (if not empty): {0}" -f $SelectedQueryDisplayName | Write-LogOutput -LogType DEBUG
            $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Clear()
            $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $Null

            $ClearQuery = $true
            $Private:Result.value | ForEach-Object {
                $DoIdDisplayName = "{0} - {1}" -f $_.DisplayName, $_.Id
                $Script:RunTimeData.QueryListCache.QueryList += @{
                    $_.Id = $_.DisplayName
                }
                if ($Script:AppConfig.MyQueriesOnly -and $null -ne $SqlQueryViewContents -and $_.Id -notin $SqlQueryViewContents.$($Script:RunTimeData.DataobjdlgAspxAttributeMapping.SqlQueryDoId)) {
                    "Skip query {0} because of 'Filter My Queries' is enabled" -f $DoIdDisplayName | Write-LogOutput -LogType DEBUG
                    if ($null -ne $SelectedQuery -and $SelectedQuery -eq $DoIdDisplayName) {
                        "Selected query {0} is filtered, clear selected query" -f $DoIdDisplayName | Write-LogOutput -LogType DEBUG
                        $SelectedQuery = $null
                    }
                }
                else {
                    if ($Script:AppConfig.MyQueriesOnly -and $null -ne $SqlQueryViewContents -and $_.Id -notin $SqlQueryViewContents.$($Script:RunTimeData.DataobjdlgAspxAttributeMapping.SqlQueryDoId)) {
                        "Add query {0} because of 'Filter My Queries' is enabled" -f $DoIdDisplayName | Write-LogOutput -LogType DEBUG
                    }
                    else {
                        "Add query {0}" -f $DoIdDisplayName | Write-LogOutput -LogType DEBUG
                    }
                    $ComboBoxSelectQueryItem = New-Object System.Windows.Controls.ComboBoxItem
                    $ComboBoxSelectQueryItem.Content = $DoIdDisplayName
                    $Script:MainWindowForm.Elements.ComboBoxSelectQuery.Items.Add($ComboBoxSelectQueryItem) | Out-Null
                }
                if ($ClearQuery -and $null -ne $SelectedQuery -and $SelectedQuery -eq $DoIdDisplayName) {
                    "Set query {0} as selected query" -f $DoIdDisplayName | Write-LogOutput -LogType DEBUG
                    $Script:MainWindowForm.Elements.ComboBoxSelectQuery.SelectedItem = $ComboBoxSelectQueryItem
                    "Set query display name to: {0}" -f $SelectedQueryDisplayName | Write-LogOutput -LogType DEBUG
                    $Script:MainWindowForm.Elements.TextBoxDisplayName.Text = $SelectedQueryDisplayName
                    $ClearQuery = $false
                }
            }
            if ($ClearQuery) {
                "Clear editor window because query is not set" | Write-LogOutput -LogType DEBUG
                Set-EditorValue
            }
            if ($null -ne $Script:PopUpWindowQueryRefresh) {
                $Script:PopUpWindowQueryRefresh.Close()
            }
        }
        else {
            "Query list retrieved from cache! Click `"Refresh Queries`" to refresh queries" | Write-LogOutput -LogType INFO
        }

        $Script:MainWindowForm.Elements.ComboBoxSelectQuery.IsEnabled = $True
        $Script:MainWindowForm.Elements.ButtonRefreshQueries.IsEnabled = $True
        $Script:MainWindowForm.Elements.CheckboxMyQueries.IsEnabled = $True
        $Script:MainWindowForm.Elements.ButtonShowSqlSchema.IsEnabled = $true
        $Script:RunTimeData.QueryListCache.LastRefresh = $CurrentTimestamp
        "{0} queries retrieved!" -f ($Script:RunTimeData.QueryListCache.QueryList | Measure-Object).Count | Write-LogOutput

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Update-SqlSchemaWindow {

    try {
        if ($null -ne $Script:TreeViewSqlSchema) {
            $Script:TreeViewSqlSchema.Dispatcher.Invoke({
                    $null
                })
        }
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Update-SqlSchemaWindowPosition {

    try {
        $Script:SqlSchemaWindowForm.PositionManager.MainWindowRight = [Int]::Abs($Script:MainWindowForm.Definition.Left) + [Int]::Abs($Script:MainWindowForm.Definition.Width)
        "PositionManagerSqlSchemaWindow MainWindowRight: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.MainWindowRight | Write-LogOutput -LogType DEBUG
        $Script:SqlSchemaWindowForm.PositionManager.MainWindowBottom = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:MainWindowForm.Definition.Height)
        "PositionManagerSqlSchemaWindow MainWindowBottom: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.MainWindowRight | Write-LogOutput -LogType DEBUG
        $Script:SqlSchemaWindowForm.PositionManager.ChildWindowRight = [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Left) + [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Width)
        "PositionManagerSqlSchemaWindow ChildWindowRight: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.ChildWindowRight | Write-LogOutput -LogType DEBUG
        $Script:SqlSchemaWindowForm.PositionManager.ChildWindowBottom = [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Top) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Height)
        "PositionManagerSqlSchemaWindow ChildWindowBottom: {0}" -f $Script:SqlSchemaWindowForm.PositionManager.ChildWindowBottom | Write-LogOutput -LogType DEBUG

        if ([Int]::Abs($Script:SqlSchemaWindowForm.Definition.Left) -lt [Int]::Abs($Script:MainWindowForm.Definition.Left)) {
            $Script:SqlSchemaWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) + [Int]::Abs($Script:MainWindowForm.Definition.Width)
            "SqlSchemaWindowForm Definition Left: {0}" -f $Script:SqlSchemaWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG

        }
        elseif ($Script:SqlSchemaWindowForm.PositionManager.ChildWindowRight -gt $Script:SqlSchemaWindowForm.PositionManager.MainWindowRight) {
            $Script:SqlSchemaWindowForm.Definition.Left = [Int]::Abs($Script:MainWindowForm.Definition.Left) - $Script:SqlSchemaWindowForm.Definition.Width
            "SqlSchemaWindowForm Definition Left: {0}" -f $Script:SqlSchemaWindowForm.Definition.Left | Write-LogOutput -LogType DEBUG
        }

        if ($Script:SqlSchemaWindowForm.Definition.Top -lt [Int]::Abs($Script:MainWindowForm.Definition.Top)) {
            $Script:SqlSchemaWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top) + [Int]::Abs($Script:MainWindowForm.Definition.Height)
            "SqlSchemaWindowForm Definition Top: {0}" -f $Script:SqlSchemaWindowForm.Definition.Top | Write-LogOutput -LogType DEBUG
        }
        elseif ($Script:PositionManager.ChildWindowBottom -gt $MainWindowBottom) {
            $Script:SqlSchemaWindowForm.Definition.Top = [Int]::Abs($Script:MainWindowForm.Definition.Top) - [Int]::Abs($Script:SqlSchemaWindowForm.Definition.Height)
            "SqlSchemaWindowForm Definition Top: {0}" -f $Script:SqlSchemaWindowForm.Definition.Top | Write-LogOutput -LogType DEBUG
        }

    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR
    }
}
function Write-LogOutput {
    PARAM(
        [parameter(Mandatory = $false, Position = 0, ValueFromPipeline = $True)]
        [string]$Message,
        [ValidateSet("DEBUG", "INFO", "ERROR", "VERBOSE", "WARNING", "FATAL", "LOG", "VERBOSE2")]
        [string]$LogType = "INFO",
        [switch]$SkipDialog
    )

    try {

        if ($null -eq $Message) {
            $Message = "-"
        }
        $DateTimeObject = Get-Date
        $DateTime = $DateTimeObject.ToString("yyyy-MM-dd HH:mm:ss")
        if ($Script:RunTimeConfig.Logging.LogLevelSetting -in ("VERBOSE", "VERBOSE2")) {
            $DateTime = $DateTimeObject.ToString("o")
        }

        $PSCallStack = Get-PSCallStack
        try {
            $Command = $null
            $Command = $PSCallStack[1]
            if ([string]::IsNullOrWhiteSpace($Command.Command)) {
(Get-PSCallStack) | ForEach-Object {
                    if ([string]::IsNullOrWhiteSpace($Command.Command) -and $_.Command -ne $MyInvocation.MyCommand -and ![string]::IsNullOrWhiteSpace($_.Command)) {
                        $Command = $_
                    }
                }
            }
            $CalledFrom = "{0} ({1})" -f $Command.Command, $Command.ScriptLineNumber
        }
        catch {
            $CalledFrom = $null
        }
        $LogMessage = @{
            Text        = "{0} - {1} - {2}: {3}" -f $DateTime, $LogType, $CalledFrom, $Message
            Show        = $false
            ShowWarning = $false
            ShowError   = $false
            ShowVerbose = $false
            Color       = "White"
        }

        $LogMessageDialog = @{
            Show        = $false
            Text        = $Message
            DialogTitle = $null
            DialogIcon  = $null
        }

        switch ($Script:RunTimeConfig.Logging.LogLevelSetting) {
            { $_ -eq "VERBOSE2" -and $LogType -in @( "DEBUG", "INFO", "ERROR", "VERBOSE", "WARNING", "FATAL", "LOG", "VERBOSE2") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "Gray"
            }
            { $_ -eq "VERBOSE" -and $LogType -in @( "DEBUG", "INFO", "ERROR", "VERBOSE", "WARNING", "FATAL", "LOG") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "Magenta"
            }
            { $_ -eq "DEBUG" -and $LogType -in @( "DEBUG", "INFO", "ERROR", "WARNING", "FATAL", "LOG") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "Cyan"
            }
            { $_ -eq "INFO" -and $LogType -in @( "INFO", "ERROR", "WARNING", "FATAL", "LOG") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "White"
            }
            { $_ -eq "WARNING" -and $LogType -in @(  "ERROR", "WARNING", "FATAL", "LOG") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "Yellow"
            }
            { $_ -in @("ERROR", "FATAL") -and $LogType -in @(  "ERROR", "FATAL", "LOG") } {
                $LogMessage.Show = $true
                $LogMessage.Color = "Red"
            }
            Default {
                $LogMessage.Show = $false
            }
        }

        switch ($LogType) {
            { $_ -eq "VERBOSE2" -and $LogMessage.Show } {
                if (!$Script:RunTimeConfig.VerboseParameterSet -and $Script:RunTimeConfig.LogToConsole) {
                    $LogMessage.ShowVerbose = $true
                }
            }
            { $_ -eq "VERBOSE" -and $LogMessage.Show } {
                if (!$Script:RunTimeConfig.VerboseParameterSet -and $Script:RunTimeConfig.LogToConsole) {
                    $LogMessage.ShowVerbose = $true
                }
            }
            { $_ -eq "DEBUG" -and $LogMessage.Show } {}
            { $_ -eq "INFO" -and $LogMessage.Show } {}
            { $_ -eq "WARNING" -and $LogMessage.Show } {
                $LogMessage.ShowWarning = $true
                $LogMessageDialog.Show = $true
                $LogMessageDialog.Text = "Warning:`r`n`r`n{0}" -f $LogMessageDialog.Text
                $LogMessageDialog.Title = "Warning"
                $LogMessageDialog.Icon = [System.Windows.Forms.MessageBoxIcon]::Warning
            }
            { $_ -in @("ERROR", "FATAL") -and $LogMessage.Show } {
                try {
                    $CallStack = $null # Get-PSCallStack | ConvertTo-Json -Depth 15 -ErrorAction SilentlyContinue
                    "{0}`r`n{1}" -f $LogMessage.Text, $CallStack | Write-Verbose
                }
                catch {}
                $LogMessage.ShowError = $true
                $LogMessageDialog.Show = $true
                $LogMessageDialog.Text = "Failure occurred:`r`n`r`n{0}" -f $LogMessageDialog.Text
                $LogMessageDialog.Title = "Error"
                $LogMessageDialog.Icon = [System.Windows.Forms.MessageBoxIcon]::Error
            }
            { $_ -eq "LOG" -and $LogMessage.Show } {}
            Default {}
        }

        if ($LogMessage.Show) {
            $Script:RunTimeConfig.Logging.AppLogObject.Add(($LogMessage.Text) -join "`r`n")
            if ($Script:RunTimeConfig.LogToConsole) {
                $LogMessage.Text | Write-Host -ForegroundColor $LogMessage.Color
            }
        }
        if ($LogMessage.ShowVerbose) {
            $LogMessage.Text | Write-Verbose
        }
        if ($LogMessageDialog.Show -and !$SkipDialog) {
            if ($null -ne $Script:MainWindowForm -and $null -ne $Script:MainWindowForm.Definition -and $Script:MainWindowForm.Definition.IsVisible) {
                [System.Windows.Forms.MessageBox]::Show($LogMessageDialog.Text, $LogMessageDialog.Title, [System.Windows.Forms.MessageBoxButtons]::OK, $LogMessageDialog.Icon)
            }
            else {
                if ($LogMessage.ShowWarning) {
                    $LogMessage.Text | Write-Warning
                }
                elseif ($LogMessage.ShowError) {
                    $LogMessage.Text | Write-Error
                }
                else {
                    $LogMessage.Text | Write-Host -ForegroundColor $LogMessage.Color
                }
            }
        }
        if ($LogMessage.ShowError) {
            $LogMessage.Text | Write-Error
        }
        if ($null -ne $Script:TextBoxLog -and $Script:TextBoxLog.IsLoaded) {
            if (Invoke-LogWindowScrollToEnd) {
                $Script:TextBoxLog.ScrollToEnd()
            }
        }
    }
    catch {
        $_.Exception.Message | Write-Error
    }
}
function Invoke-OmadaSqlTroubleshooter {
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'StartVariables', Justification = 'The CurrentPoperties variable is used in a function called from here')]
    [cmdletbinding()]
    PARAM(
        [ValidateSet("INFO", "DEBUG", "VERBOSE", "WARNING", "ERROR", "FATAL", "VERBOSE2")]
        [string]$LogLevel,
        [switch]$Reset,
        [switch]$LogToConsole
    )
    $Error.Clear()

    $StartVariables = Get-Variable
    $ApplicationName = "OmadaSqlTroubleshooter"

    $Script:RunTimeConfig = @{
        ScriptName         = "OmadaSqlTroubleshooter.ps1"
        ApplicationTitle   = ""
        ModuleFolder       = Split-Path (Get-Module OmadaSqlTroubleShooter).Path
        AppDataFolder      = Join-Path ([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::ApplicationData)) -ChildPath $ApplicationName
        Logging            = [PSCustomObject]@{
            LogToConsole        = $LogToConsole.IsPresent -or $false
            LogLevel            = $null
            VerboseParameterSet = $PSCmdlet.MyInvocation.BoundParameters.Keys.Contains("Verbose")
            LogLevelSetting     = [string]::IsNullOrWhiteSpace($LogLevel) ? $null : $LogLevel
            AppLogObject        = [System.Collections.ObjectModel.ObservableCollection[string]]::new()
        }
        StopWatch          = $null
        LastWindowMeasured = Get-Date
        ConfigFile         = [PSCustomObject]@{
            Path = $null
            Name = $null
        }
        AuthenticationSet  = $false
        OutputFileName     = $null
    }
    Get-ChildItem -Path (Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "Lib\Functions") -Filter *.ps1 | ForEach-Object {
        . $_.FullName
    }
    Initialize-OmadaSqlTroubleShooter

    $SplashScreenForm = Open-SplashScreenForm
    "Loading Main Window Object" | Write-LogOutput -LogType DEBUG
    $Script:MainWindowForm = New-FormObject -FormPath (Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "lib\ui\MainWindow.xaml")
    $Script:RunTimeConfig.ApplicationTitle = $Script:MainWindowForm.Definition.Title.ToString()
    "Get WebView" | Write-LogOutput -LogType DEBUG
    $Script:Webview.Object = $Script:MainWindowForm.Definition.FindName("webView21")


    try {
        "Read Events" | Write-LogOutput -LogType DEBUG
        Get-ChildItem -Path (Join-Path $Script:RunTimeConfig.ModuleFolder -ChildPath "Lib\Events") -Filter *.ps1 | ForEach-Object {
            . $_.FullName
        }
    }
    catch {
        if ($_.Exception.Response.StatusCode -eq "NotFound") {
            "SQL Troubleshooting Object not found or OData endpoint for SQL Troubleshooting is not found. Is it enable for OData? Please check the data object type properties!" | Write-LogOutput -LogType ERROR
        }
        else {
            $_.Exception.Message | Write-LogOutput -LogType ERROR
        }
    }

    try {
        "Show Splash Screen" | Write-LogOutput -LogType DEBUG
        [void]$SplashScreenForm.Show()
        [System.Windows.Forms.Application]::DoEvents()

        "Application '{0}': Start initialization..." -f $Script:RunTimeConfig.ApplicationTitle | Write-Host -ForegroundColor Green
        Initialize-ConfigSettings

        Close-SplashScreenForm
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR -SkipDialog
        Close-SplashScreenForm
        Clear-Variables
    }

    try {
        $Message = "Application '{0}': Initialized!" -f $Script:RunTimeConfig.ApplicationTitle
        $Message | Write-Host -ForegroundColor Green
        $Message | Write-LogOutput -LogType DEBUG
        "Loading Main Window with settings:`r`n{0}" -f ($Script:AppConfig | ConvertTo-Json) | Write-LogOutput -LogType DEBUG

        [void]$Script:MainWindowForm.Definition.ShowDialog()
        $Message = "Application '{0}': Closed, cleaning-up!" -f $Script:RunTimeConfig.ApplicationTitle
        $Message | Write-Host -ForegroundColor Green
        $Message | Write-LogOutput -LogType DEBUG
        "Invoke-ConfigSetting" | Write-LogOutput -LogType DEBUG
        Invoke-ConfigSetting
        "Close Main Window" | Write-LogOutput -LogType DEBUG
        $Script:MainWindowForm.Definition.Close() | Out-Null
        $Script:Webview.Object.Dispose() | Out-Null
    }
    catch {
        $_.Exception.Message | Write-LogOutput -LogType ERROR -SkipDialog
        Close-SplashScreenForm
        Clear-Variables
    }

    Pop-Location
    Clear-Variables
    "Application '{0}': Clean-up complete!" -f $Script:RunTimeConfig.ApplicationTitle | Write-Host -ForegroundColor Green
}
function Set-OmadaSqlTroubleShooterShortcut {
    PARAM(
        [switch]$NotCreateDesktopShortcut
    )
    "Create Start Menu shortcut" | Write-Host
    $LocalAppDataPath = Join-Path ([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::LocalApplicationData)) -ChildPath "OmadaSqlTroubleShooter"
    if (-not (Test-Path -Path $LocalAppDataPath)) {
        New-Item -Path $LocalAppDataPath -ItemType Directory -Force | Out-Null
    }
    $ModuleInfo = Get-Module OmadaSqlTroubleShooter
    $ModulePath = Split-Path -Path $ModuleInfo.Path -Parent
    [xml]$MainWindowXaml = Get-Content (Join-Path $ModulePath -ChildPath "lib\ui\MainWindow.xaml")
    $ScriptTitle = $MainWindowXaml.Window.Title

    $WshShell = New-Object -ComObject WScript.Shell
    $PowerShellExecPath = (Get-Command "pwsh.exe").Path
    $OmadaSqlTroubleShooterIcoPath = Join-Path $ModulePath -ChildPath "lib\ui\OmadaSqlTroubleShooter.ico"
    $ShortcutFullPath = Join-Path $WshShell.SpecialFolders("Programs") -ChildPath ("{0}.lnk" -f $ScriptTitle)
    $RunPath = Join-Path $LocalAppDataPath -ChildPath "Run.ps1"
    "Push-Location '{0}';
Import-Module -Name 'OmadaSqlTroubleShooter';
Invoke-OmadaSqlTroubleshooter;
Pop-Location;
'Window will automatically close in 5 seconds!' | Write-Host -ForegroundColor Green;
Start-Sleep -Seconds 5"
 -f $LocalAppDataPath | Set-Content $RunPath -Force -Encoding utf8
    $Arguments = ' -File "{0}"' -f $RunPath

    $WshShell = New-Object -ComObject WScript.Shell
    $Shortcut = $WshShell.CreateShortcut($ShortcutFullPath)
    $Shortcut.TargetPath = $PowerShellExecPath
    $Shortcut.WorkingDirectory = $LocalAppDataPath
    $Shortcut.Arguments = $Arguments
    $Shortcut.IconLocation = ("{0},0" -f $OmadaSqlTroubleShooterIcoPath)
    $Shortcut.Save()

    if ($NotCreateDesktopShortcut) {
        "Desktop shortcut not created" | Write-Host
    }
    else {
        Get-Item -Path $ShortcutFullPath | Copy-Item -Destination $WshShell.SpecialFolders("Desktop") -Force
        "Created desktop shortcut. Use parameter -NotCreateDesktopShortcut to skip this part." | Write-Host
    }
}