Modules/ScubaConfigApp/ScubaConfigAppHelpers/ScubaConfigAppSearchHelper.psm1

Function Show-SearchAndFilterControl{
    <#
    .SYNOPSIS
    Initializes search and filter controls for all tabs.
    .DESCRIPTION
    This Function sets up search boxes, filter dropdowns, and their event handlers for baselineControl tabs.
    #>

    param()

    Write-DebugOutput -Message "Showing search and filter controls" -Source $MyInvocation.MyCommand -Level "Info"
    #Show all search and filter controls
    Foreach($item in $synchash.UIConfigs.baselineControls) {
        $SearchAndFilterBorder = ($item.controlType + "SearchAndFilterBorder")
        $synchash.$SearchAndFilterBorder.Visibility = [System.Windows.Visibility]::Visible
    }

    # Add search and filter capability to each tab
    Add-SearchAndFilterCapability
}

Function Hide-SearchAndFilterControl {
    <#
    .SYNOPSIS
    Hides search and filter controls for all tabs.
    .DESCRIPTION
    This Function hides all search boxes and filter dropdowns for baselineControl tabs.
    #>

    param()

    Write-DebugOutput -Message "Hiding search and filter controls" -Source $MyInvocation.MyCommand -Level "Info"

    # Hide all search and filter controls
    Foreach($item in $synchash.UIConfigs.baselineControls) {
        $SearchAndFilterBorder = ($item.controlType + "SearchAndFilterBorder")
        $synchash.$SearchAndFilterBorder.Visibility = [System.Windows.Visibility]::Collapsed
    }
}



# Find the Add-SearchAndFilterCapability Function and modify it to defer initial filtering:

Function Add-SearchAndFilterCapability {
    <#
    .SYNOPSIS
    Initializes search and filter controls for all tabs.
    .DESCRIPTION
    This Function sets up search boxes, filter dropdowns, and their event handlers for baselineControl tabs.
    #>

    param()


    # Get unique criticality values dynamically from baseline data
    $criticalityValues = Get-UIConfigCriticalValues

    # Initialize for each tab type
    $tabTypes = $synchash.UIConfigs.baselineControls.controlType

    foreach ($tabType in $tabTypes)
    {
        Write-DebugOutput -Message "Initializing search and filter for $tabType tab" -Source $MyInvocation.MyCommand -Level "Verbose"

        #Clear the search and filter controls when product tabs are switched (sub tabs)
        #this fixes the issue where policies are blanked out when switching tabs
        $productTabControl = $syncHash."$($tabType)ProductTabControl"
        if ($productTabControl) {
            $productTabControl.Add_SelectionChanged({

                # Get the tab type from the sender control name
                $tabControlName = $this.Name
                $currentTabType = $tabControlName -replace 'ProductTabControl', ''

                # Get the clear search button for this tab type
                $clearButton = $syncHash."$($currentTabType)ClearSearch_Button"

                if ($clearButton) {
                    try {
                        # Programmatically trigger the clear search button click
                        $clearButton.RaiseEvent([System.Windows.RoutedEventArgs]::new([System.Windows.Controls.Primitives.ButtonBase]::ClickEvent))
                        Write-DebugOutput -Message "Auto-cleared search for $currentTabType when switching product tabs" -Source $MyInvocation.MyCommand -Level "Debug"
                    } catch {
                        # Fallback: manually clear the search and apply filter
                        $searchBox = $syncHash."$($currentTabType)Search_TextBox"
                        $criticalityComboBox = $syncHash."$($currentTabType)Criticality_ComboBox"
                        $configuredComboBox = $syncHash."$($currentTabType)Configured_ComboBox"

                        if ($searchBox) {
                            $searchBox.Tag = "Clearing" # Prevent TextChanged from triggering search
                            $searchBox.Text = $syncHash.UIConfigs.localePlaceholder.SearchPlaceholder_TextBox
                            $searchBox.Foreground = [System.Windows.Media.Brushes]::Gray
                            $searchBox.FontStyle = [System.Windows.FontStyles]::Italic
                            $searchBox.Tag = "Placeholder"

                            # Reset criticality filter to "All"
                            if ($criticalityComboBox) {
                                $criticalityComboBox.SelectedIndex = 0
                            }

                            # Reset configuration status filter to "All"
                            if ($configuredComboBox) {
                                $configuredComboBox.SelectedIndex = 0
                            }

                            # Trigger the search update
                            Set-SearchAndFilter -TabType $currentTabType
                            Write-DebugOutput -Message "Manually cleared search for $currentTabType when switching product tabs (fallback)" -Source $MyInvocation.MyCommand -Level "Debug"
                        }
                    }
                }
            }.GetNewClosure())

            Write-DebugOutput -Message "Added auto-clear search Functionality for $tabType product tabs" -Source $MyInvocation.MyCommand -Level "Verbose"
        }

        # Initialize search textbox with improved placeholder handling
        $searchTextBox = $syncHash."$($tabType)Search_TextBox"
        if ($searchTextBox) {
            # Clear any existing event handlers to prevent conflicts
            $searchTextBox.Text = ""

            # Set up placeholder behavior
            $placeholderText = $syncHash.UIConfigs.localePlaceholder.SearchPlaceholder_TextBox
            $searchTextBox.Text = $placeholderText
            $searchTextBox.Foreground = [System.Windows.Media.Brushes]::Gray
            $searchTextBox.FontStyle = [System.Windows.FontStyles]::Italic
            $searchTextBox.Tag = "Placeholder"

            # Add GotFocus event
            $searchTextBox.Add_GotFocus({
                if ($this.Tag -eq "Placeholder") {
                    $this.Tag = "Clearing" # Set temporary tag to prevent TextChanged from triggering search
                    $this.Text = ""
                    $this.Foreground = [System.Windows.Media.Brushes]::Black
                    $this.FontStyle = [System.Windows.FontStyles]::Normal
                    $this.Tag = "Active"
                }
            }.GetNewClosure())

            # Add LostFocus event
            $searchTextBox.Add_LostFocus({
                if ([string]::IsNullOrWhiteSpace($this.Text)) {
                    $this.Tag = "Clearing" # Set temporary tag to prevent TextChanged from triggering search
                    $this.Text = $placeholderText
                    $this.Foreground = [System.Windows.Media.Brushes]::Gray
                    $this.FontStyle = [System.Windows.FontStyles]::Italic
                    $this.Tag = "Placeholder"
                }
            }.GetNewClosure())

            # Add TextChanged event for real-time search
            $searchTextBox.Add_TextChanged({
                # Don't trigger search if we're in the middle of clearing/setting placeholder
                if ($this.Tag -eq "Clearing") {
                    return
                }

                # Only trigger search if not in placeholder mode
                if ($this.Tag -ne "Placeholder") {
                    # Trigger search whether text is present or empty (to show all items when cleared)
                    Set-SearchAndFilter -TabType $tabType
                }
            }.GetNewClosure())

            Write-DebugOutput -Message "Search textbox initialized for $tabType" -Source $MyInvocation.MyCommand -Level "Verbose"
        }

        # Initialize clear search button
        $clearButton = $syncHash."$($tabType)ClearSearch_Button"
        # Initialize criticality filter combobox with dynamic values
        $criticalityComboBox = $syncHash."$($tabType)Criticality_ComboBox"


        $clearButton.Add_Click({
            $searchBox = $syncHash."$($tabType)Search_TextBox"
            $criticalityComboBox = $syncHash."$($tabType)Criticality_ComboBox"
            $configuredComboBox = $syncHash."$($tabType)Configured_ComboBox"

            if ($searchBox) {
                $searchBox.Tag = "Clearing" # Prevent TextChanged from triggering search
                $searchBox.Text = $syncHash.UIConfigs.localePlaceholder.SearchPlaceholder_TextBox
                $searchBox.Foreground = [System.Windows.Media.Brushes]::Gray
                $searchBox.FontStyle = [System.Windows.FontStyles]::Italic
                $searchBox.Tag = "Placeholder"

                # Reset default selection to "All" for both filters
                if ($criticalityComboBox) {
                    $criticalityComboBox.SelectedIndex = 0
                }
                if ($configuredComboBox) {
                    $configuredComboBox.SelectedIndex = 0
                }

                # Now trigger the search with cleared state
                Set-SearchAndFilter -TabType $tabType
            }
        }.GetNewClosure())



        # Clear existing items
        $criticalityComboBox.Items.Clear()

        # Add "All" option
        $allItem = New-Object System.Windows.Controls.ComboBoxItem
        $allItem.Content = "All Baselines"
        $allItem.Tag = "ALL_BASELINES"  # Use all values as tag
        [void]$criticalityComboBox.Items.Add($allItem)

        # Add specific criticality values dynamically
        foreach ($criticality in $criticalityValues) {
            $item = New-Object System.Windows.Controls.ComboBoxItem
            $item.Content = "$criticality only"
            $item.Tag = $criticality
            [void]$criticalityComboBox.Items.Add($item)
            Write-DebugOutput -Message "Added criticality option: $criticality" -Source $MyInvocation.MyCommand -Level "Verbose"
        }

        # Set default selection to "All"
        $criticalityComboBox.SelectedIndex = 0

        # Add filter event handler
        $criticalityComboBox.Add_SelectionChanged({
            # Get current configuration status from the other dropdown
            $configuredComboBox = $syncHash."$($tabType)Configured_ComboBox"
            $configurationStatus = if ($configuredComboBox -and $configuredComboBox.SelectedItem) {
                $configuredComboBox.SelectedItem.Tag
            } else {
                "ALL_CONFIGURATIONS"
            }
            Set-SearchAndFilter -TabType $tabType -Criticality $this.SelectedItem.Tag -ConfigurationStatus $configurationStatus
        }.GetNewClosure())

        Write-DebugOutput -Message "Criticality filter initialized for $tabType with $($criticalityValues.Count) values" -Source $MyInvocation.MyCommand -Level "Info"

        # Initialize configuration status filter combobox
        $configuredComboBox = $syncHash."$($tabType)Configured_ComboBox"
        if ($configuredComboBox) {
            # Clear existing items
            $configuredComboBox.Items.Clear()

            # Add "All" option
            $allConfigItem = New-Object System.Windows.Controls.ComboBoxItem
            $allConfigItem.Content = "All Configurations"
            $allConfigItem.Tag = "ALL_CONFIGURATIONS"
            [void]$configuredComboBox.Items.Add($allConfigItem)

            # Add "Configured" option (cards with "Saved" tag)
            $configuredItem = New-Object System.Windows.Controls.ComboBoxItem
            $configuredItem.Content = "Configured Only"
            $configuredItem.Tag = "CONFIGURED"
            [void]$configuredComboBox.Items.Add($configuredItem)

            # Add "Not Configured" option (cards with null/empty tag)
            $notConfiguredItem = New-Object System.Windows.Controls.ComboBoxItem
            $notConfiguredItem.Content = "Not Configured Only"
            $notConfiguredItem.Tag = "NOT_CONFIGURED"
            [void]$configuredComboBox.Items.Add($notConfiguredItem)

            # Set default selection to "All"
            $configuredComboBox.SelectedIndex = 0

            # Add filter event handler
            $configuredComboBox.Add_SelectionChanged({
                # Get current criticality from the other dropdown
                $criticalityComboBox = $syncHash."$($tabType)Criticality_ComboBox"
                $criticality = if ($criticalityComboBox -and $criticalityComboBox.SelectedItem) {
                    $criticalityComboBox.SelectedItem.Tag
                } else {
                    "ALL_BASELINES"
                }
                Set-SearchAndFilter -TabType $tabType -Criticality $criticality -ConfigurationStatus $this.SelectedItem.Tag
            }.GetNewClosure())

            Write-DebugOutput -Message "Configuration status filter initialized for $tabType" -Source $MyInvocation.MyCommand -Level "Info"
        }

    }#end foreach

    Write-DebugOutput -Message "Search and filter initialization completed" -Source $MyInvocation.MyCommand -Level "Info"

    # IMPORTANT: Don't apply initial filtering here - let it happen when products are loaded
}

Function Set-SearchAndFilter {
    <#
    .SYNOPSIS
    Applies search and filter criteria to policy cards.
    .DESCRIPTION
    This Function filters the display of policy cards based on search text, criticality selection, and configuration status.
    #>

    param(
        [string]$TabType,
        [string]$Criticality = "ALL_BASELINES",  # Default to showing all baselines
        [string]$ConfigurationStatus = "ALL_CONFIGURATIONS"  # Default to showing all configurations
    )

    # Get search criteria
    $searchTextBox = $syncHash."$($TabType)Search_TextBox"
    $criticalityComboBox = $syncHash."$($TabType)Criticality_ComboBox"
    $configuredComboBox = $syncHash."$($TabType)Configured_ComboBox"
    $resultCountTextBlock = $syncHash."$($TabType)ResultCount_TextBlock"

    # Get current filter values if not provided as parameters
    if ($Criticality -eq "ALL_BASELINES" -and $criticalityComboBox -and $criticalityComboBox.SelectedItem) {
        $Criticality = $criticalityComboBox.SelectedItem.Tag
    }
    if ($ConfigurationStatus -eq "ALL_CONFIGURATIONS" -and $configuredComboBox -and $configuredComboBox.SelectedItem) {
        $ConfigurationStatus = $configuredComboBox.SelectedItem.Tag
    }

    $searchText = ""
    # Only use search text if not in placeholder mode
    if ($searchTextBox -and $searchTextBox.Tag -ne "Placeholder" -and ![string]::IsNullOrWhiteSpace($searchTextBox.Text)) {
        $searchText = $searchTextBox.Text.Trim()
    }

    Write-DebugOutput -Message "Applying filter: Search='$searchText', Criticality='$Criticality', ConfigurationStatus='$ConfigurationStatus'" -Source $MyInvocation.MyCommand -Level "Verbose"

    # Apply filter to each product tab
    $productTabControl = $syncHash."$($TabType)ProductTabControl"
    if (-not $productTabControl) {
        Write-DebugOutput -Message "Product tab control not found for $TabType" -Source $MyInvocation.MyCommand -Level "Error"
        return
    }

    # Check if there are any enabled product tabs
    $enabledTabs = $productTabControl.Items | Where-Object { $_.IsEnabled }
    if (-not $enabledTabs -or $enabledTabs.Count -eq 0) {
        Write-DebugOutput -Message "No enabled product tabs found for $TabType - skipping filter" -Source $MyInvocation.MyCommand -Level "Verbose"
        # Update result count to show 0
        if ($resultCountTextBlock) {
            $resultCountTextBlock.Text = "0 policies"
        }
        return
    }

    $totalVisible = 0

    foreach ($productTab in $productTabControl.Items) {
        if (-not $productTab.IsEnabled) { continue }

        # Find the content container for this product
        $contentContainer = $null
        if ($productTab.Content -is [System.Windows.Controls.ScrollViewer]) {
            $contentContainer = $productTab.Content.Content
        } elseif ($productTab.Content -is [System.Windows.Controls.StackPanel]) {
            $contentContainer = $productTab.Content
        } else {
            # Look for ScrollViewer in the content
            foreach ($child in $productTab.Content.Children) {
                if ($child -is [System.Windows.Controls.ScrollViewer]) {
                    $contentContainer = $child.Content
                    break
                }
            }
        }

        if (-not $contentContainer) {
            Write-DebugOutput -Message "Content container not found for product tab: $($productTab.Header)" -Source $MyInvocation.MyCommand -Level "Error"
            continue
        }

        $visibleInThisProduct = 0

        # Filter cards in this product container
        # First, get only the Border controls (actual policy cards)
        $policyCards = $contentContainer.Children | Where-Object { $_ -is [System.Windows.Controls.Border] }
        $otherControls = $contentContainer.Children | Where-Object { $_ -isnot [System.Windows.Controls.Border] }

        # Handle policy cards with filtering
        foreach ($card in $policyCards) {
            # Safety check during card iteration
            if ($syncHash.isClosing -or $syncHash.isClosed) {
                break
            }

            try {
                $shouldShow = Test-SearchAndFilter -Card $card -SearchText $searchText -Criticality $Criticality -ConfigurationStatus $ConfigurationStatus

                if ($shouldShow) {
                    $card.Visibility = [System.Windows.Visibility]::Visible
                    $visibleInThisProduct++
                } else {
                    $card.Visibility = [System.Windows.Visibility]::Collapsed
                }
            } catch {
                # If error filtering individual card, make it visible by default
                Write-DebugOutput -Message "Error filtering card: $($_.Exception.Message)" -Source $MyInvocation.MyCommand -Level "Error"
                $card.Visibility = [System.Windows.Visibility]::Visible
                $visibleInThisProduct++
            }
        }

        # Handle other controls (like TextBlocks for messages)
        foreach ($control in $otherControls) {
            if ($syncHash.isClosing -or $syncHash.isClosed) {
                break
            }

            # For message controls, show them only when no policy cards are visible
            if ($control -is [System.Windows.Controls.TextBlock] -and
                ($control.Text -like "*No policies*" -or $control.Text -like "*No data*")) {
                # Show "No policies" message only when no cards are visible
                if ($visibleInThisProduct -eq 0) {
                    $control.Visibility = [System.Windows.Visibility]::Visible
                } else {
                    $control.Visibility = [System.Windows.Visibility]::Collapsed
                }
            } else {
                # Keep other controls visible by default
                $control.Visibility = [System.Windows.Visibility]::Visible
            }
        }

        $totalVisible += $visibleInThisProduct
        Write-DebugOutput -Message "Product $($productTab.Header): $visibleInThisProduct visible cards" -Source $MyInvocation.MyCommand -Level "Verbose"
    }

    # Update result count
    if ($resultCountTextBlock) {
        $resultCountTextBlock.Text = "$totalVisible policies"
    }

    Write-DebugOutput -Message "Filter applied: $totalVisible policies visible total" -Source $MyInvocation.MyCommand -Level "Info"
}

Function Test-SearchAndFilter {
    <#
    .SYNOPSIS
    Tests if a policy card matches the current search and filter criteria.
    .DESCRIPTION
    This Function evaluates whether a policy card should be visible based on search text, criticality filter, and configuration status.
    Assumes the card Tag property contains baseline data with id, name, criticality, and rationale properties.
    Card objects themselves may have configuration status information (e.g., "Saved" tag for configured cards).
    #>

    param(
        [Parameter(Mandatory=$true)]
        [System.Windows.FrameworkElement]$Card,  # Changed from Border to FrameworkElement to be more flexible
        [string]$SearchText,
        [string]$Criticality,
        [string]$ConfigurationStatus = "ALL_CONFIGURATIONS"
    )

    # Safety check - return true if window is closing or card is invalid
    if ($syncHash.isClosing -or $syncHash.isClosed -or !$Card) {
        return $true
    }

    # Only process Border controls - other controls should be handled by the caller
    if ($Card -isnot [System.Windows.Controls.Border]) {
        Write-DebugOutput -Message "Test-SearchAndFilter called with non-Border control: $($Card.GetType().Name)" -Source $MyInvocation.MyCommand -Level "Error"
        return $true
    }

    try {
        # Get card data from Tag property - we now always set this with baseline data
        $cardData = $Card.Tag

        # If no tag data, always show the card
        if (-not $cardData) {
            return $true
        }

        # Apply search filter
        if (![string]::IsNullOrWhiteSpace($SearchText)) {
            $searchMatch = $false

            # Search in policy ID
            if ($cardData.id -and $cardData.id -like "*$SearchText*") {
                $searchMatch = $true
            }

            # Search in policy name
            if ($cardData.name -and $cardData.name -like "*$SearchText*") {
                $searchMatch = $true
            }

            # Search in description/rationale
            if ($cardData.rationale -and $cardData.rationale -like "*$SearchText*") {
                $searchMatch = $true
            }

            if (-not $searchMatch) {
                return $false
            }
        }

        # Apply criticality filter - fixed logic
        if (![string]::IsNullOrWhiteSpace($Criticality) -and $Criticality -ne "ALL_BASELINES") {
            # Show only cards that match the selected criticality
            if ($cardData.criticality -ne $Criticality) {
                return $false
            }
        }

        # Apply configuration status filter
        if (![string]::IsNullOrWhiteSpace($ConfigurationStatus) -and $ConfigurationStatus -ne "ALL_CONFIGURATIONS") {
            # Check if the card object has configuration status information
            $isConfigured = $false

            # Method 1: Check if the card itself has any "Saved" indicators
            # This could be in the card's Tag, Name, or other properties
            if ($Card.Tag -and ($Card.Tag -eq "Saved")) {
                $isConfigured = $true
            }

            # Method 2: Look for CheckBox controls within the card that have "Saved" tag
            # This is the primary way the app marks configured policies
            if (-not $isConfigured) {
                try {
                    # Function to recursively search for CheckBox with "Saved" tag
                    function Find-SavedCheckBox($element) {
                        if (-not $element) {
                            return $false
                        }

                        # Check if this element is a CheckBox with "Saved" tag
                        if ($element -is [System.Windows.Controls.CheckBox]) {
                            if ($element.Tag -eq "Saved") {
                                return $true
                            }
                            # Debug: Log all checkboxes found
                            Write-DebugOutput -Message "Found CheckBox with Tag: '$($element.Tag)'" -Source "Find-SavedCheckBox" -Level "Debug"
                        }

                        # Search in child elements using direct property access
                        # Skip LogicalTreeHelper.GetChildren() as it doesn't work properly in PowerShell

                        # Try visual tree for more complex layouts
                        try {
                            if ($element -is [System.Windows.DependencyObject]) {
                                $childCount = [System.Windows.Media.VisualTreeHelper]::GetChildrenCount($element)
                                for ($i = 0; $i -lt $childCount; $i++) {
                                    $child = [System.Windows.Media.VisualTreeHelper]::GetChild($element, $i)
                                    if (Find-SavedCheckBox $child) {
                                        return $true
                                    }
                                }
                            }
                        } catch {
                            # Visual tree navigation failed
                            return $false
                        }

                        # For Panel controls, try the Children collection
                        try {
                            if ($element -is [System.Windows.Controls.Panel] -and $element.Children) {
                                foreach ($child in $element.Children) {
                                    if (Find-SavedCheckBox $child) {
                                        return $true
                                    }
                                }
                            }
                        } catch {
                            # Panel children access failed
                            return $false
                        }

                        # For ContentControl (like Border), check Content property
                        try {
                            if ($element -is [System.Windows.Controls.ContentControl] -and $element.Content -and $element.Content -ne $element) {
                                if (Find-SavedCheckBox $element.Content) {
                                    return $true
                                }
                            }
                        } catch {
                            # Content access failed
                            return $false
                        }

                        return $false
                    }

                    $isConfigured = Find-SavedCheckBox $Card

                } catch {
                    # If there's an error searching for saved checkboxes, assume not configured
                    Write-DebugOutput -Message "Error checking configuration status: $($_.Exception.Message)" -Source $MyInvocation.MyCommand -Level "Debug"
                    $isConfigured = $false
                }
            }

            <# Method 3: Check if the card has visible configuration data
            # Look for any TextBox, ComboBox, or other input controls with non-default values
            if (-not $isConfigured) {
                try {
                    function Find-ConfiguredInputs($element) {
                        if (-not $element) {
                            return $false
                        }
 
                        # Check for TextBox with non-empty, non-placeholder text
                        if ($element -is [System.Windows.Controls.TextBox]) {
                            if (-not [string]::IsNullOrWhiteSpace($element.Text) -and
                                $element.Text -notlike "*placeholder*" -and
                                $element.Text -notlike "*Enter*" -and
                                $element.Text -notlike "*Type*") {
                                return $true
                            }
                        }
 
                        # Check for ComboBox with selected items
                        if ($element -is [System.Windows.Controls.ComboBox]) {
                            if ($element.SelectedIndex -gt 0 -or $element.SelectedItem) {
                                return $true
                            }
                        }
 
                        # Check for CheckBox that's checked (but not the main policy checkbox)
                        if ($element -is [System.Windows.Controls.CheckBox] -and $element.IsChecked -eq $true) {
                            # Skip the main policy checkbox (usually has different styling)
                            if (-not ($element.Name -like "*Policy*" -or $element.Style -and $element.Style.TargetType -eq [System.Windows.Controls.CheckBox])) {
                                return $true
                            }
                        }
 
                        # Recursively check children (simplified version)
                        try {
                            if ($element -is [System.Windows.Controls.Panel] -and $element.Children) {
                                foreach ($child in $element.Children) {
                                    if (Find-ConfiguredInputs $child) {
                                        return $true
                                    }
                                }
                            }
 
                            if ($element -is [System.Windows.Controls.ContentControl] -and $element.Content -and $element.Content -ne $element) {
                                if (Find-ConfiguredInputs $element.Content) {
                                    return $true
                                }
                            }
                        } catch {
                            # Ignore errors in recursion
                            return $false
                        }
 
                        return $false
                    }
 
                    $isConfigured = Find-ConfiguredInputs $Card
 
                } catch {
                    # If there's an error checking for configured inputs, assume not configured
                    Write-DebugOutput -Message "Error checking for configured inputs: $($_.Exception.Message)" -Source $MyInvocation.MyCommand -Level "Debug"
                    $isConfigured = $false
                }
            }
            #>


            # Debug logging to understand what's happening
            if ($cardData.id) {
                Write-DebugOutput -Message "Card $($cardData.id): isConfigured = $isConfigured, requested filter = $ConfigurationStatus" -Source $MyInvocation.MyCommand -Level "Debug"
            }

            # Apply the filter
            switch ($ConfigurationStatus) {
                "CONFIGURED" {
                    if (-not $isConfigured) {
                        return $false
                    }
                }
                "NOT_CONFIGURED" {
                    if ($isConfigured) {
                        return $false
                    }
                }
            }
        }

        return $true

    } catch {
        # If any error occurs during filtering (e.g., during window close), just show the card
        Write-DebugOutput -Message "Error in Test-SearchAndFilter: $($_.Exception.Message)" -Source $MyInvocation.MyCommand -Level "Error"
        return $true
    }
}
# SIG # Begin signature block
# MIIu9gYJKoZIhvcNAQcCoIIu5zCCLuMCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDod5YuixFK0ZyK
# 1WZ488veR4Rw86gm/TFXgVJqgG1iuaCCE6MwggWQMIIDeKADAgECAhAFmxtXno4h
# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
# eE4wggdXMIIFP6ADAgECAhAP1uYgxSr4joyBpB/eZOIuMA0GCSqGSIb3DQEBCwUA
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwHhcNMjUwMjA4MDAwMDAwWhcNMjYwMTE1MjM1OTU5WjBfMQsw
# CQYDVQQGEwJVUzEdMBsGA1UECBMURGlzdHJpY3Qgb2YgQ29sdW1iaWExEzARBgNV
# BAcTCldhc2hpbmd0b24xDTALBgNVBAoTBENJU0ExDTALBgNVBAMTBENJU0EwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCXm3O0IOQzt0tbPPKAv4IrrzOf
# QjE4Mb9j1zLL1GehaE35ddnoitE7l8OmVEeTLwPH+UpI7DfynUCjLb8HGcsuHO0H
# aUuVFR3FNyvGByYATUTA+bQ9UgcwCoPyL48cDmdqFzheQ/KsC+FhI4uEpYiB/6Jp
# Q0UL0SUVfC8O8+1ioUXAwdMt3G8bT3x6WaEmAbGqM5yC5fd7rKZEmpLzpA6bP2Xc
# QMwi6Jn1m4AvL/jJrXvPyVUK9UlbjobKjiVg6a/UBgFrq8cU7Q1w/e5ijy6XA+aC
# Z7SICqimtCW4wbrvodZL0yFeZIxN9qJ24hvrVGf7P/ANTzkoGHuHLwpMIOjBrpA+
# ig3jBTjY1xE2DYgHWcKHsSHEbOxStk+qHsn2J5i9GK+nwS7GmMqIRaEwy+dbfh6l
# Q2jI4PO6kPk0ePnB3jTD/bEkdbRXpuq3aUAMS4ZSESer+CnzeBLEXvHrVVs4yHrf
# RPmLOX+T43FEf6iAY7Ta3ahn0icLtCtauJ9/jmMigM/l1IfaAF6E/SoCHc6G6S9F
# 1ECU/nBkpThU5u2kufiGWBC8rV2V8D50QERbohnv3yWR5BTG8dX+NYjd7HdctRAj
# 9al3sQ/tdyVgOHUp+9KseYJthuNnh8WCoDeho/GX65QJDSJwh5uDcvNUfpeebANU
# U1GwatZ4l+EWfOc05QIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8R
# hvv+YXsIiGX0TkIwHQYDVR0OBBYEFJIsiVnihq62MAlpq96K9lNX9UCGMD4GA1Ud
# IAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNl
# cnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMw
# gbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp
# Z2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5j
# cmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0
# ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMIGUBggrBgEF
# BQcBAQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
# MFwGCCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
# cnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJ
# BgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQChGHY/dRc2BtvGT6mHR4bqoakC
# N9hyjDA+bbxJE73T2HgI5wKVmhu2JmFZ/FHmoXE4ngnLnGS+zMEoeTEfzb/MmAxF
# H+Ca/JGMDsbVf+rP+aVc1NkSpUd6u5rsR01Dimcs+pHGwpEUF1HCDFrFcl10Smcj
# b8Z+tPbIETe3yvdRyoJL2Lm6k8wvC7xfgPoMzdbKWRzTCEnVQ+B53vHBSLT4D5wW
# dq3yv6oj2fQ381wZQm16fLIedmiStUYfp0ZICqI3T6UiQ5w/DXYy05Z/1Njqu3PQ
# l2Sy/JLDZc7hBu5YH5ia1G2IFC6S9gN34jm8qhkkoo8kihsxRBbBLiiNB0z/eH7y
# jsNgyRR+Vje51Jcgte18zVQH6fRkl+HDp2nMgdgzShlKYXZzVFQvgmMu76x72P5f
# bOgzmOxCZNZh0AQUo16DdbnGvloqHCbEND2JA/0QpeB0dlWKkWiotu/MaJE8/4uU
# sxw5JSZPj8ya4WnrntJaY73TxXBHSd9CezT7lDShTgB1FkCSAov3aFwqyGH4hC+2
# MGp3Wzn03rkqVCzjmgNSIkCxQzJ+hEIvbk6GVK2yk+Q9eZQCkjRKY+EYwJNDsB9I
# w75dWMsi2S9PFBEkKZYZFgxwVaBvnWgrfxlZMOooNADSdmq5fvTH/tjR3vIEd4QP
# Dlzb9f7QLX+cvb0MjjGCGqkwghqlAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNV
# BAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0
# IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQD9bmIMUq+I6M
# gaQf3mTiLjANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgACh
# AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM
# BgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBPQC54rF6hfPq0758qj6e8Q84D
# CW41TbHWIAaoC/D1STANBgkqhkiG9w0BAQEFAASCAgB8ejjF6H0QmKhKF/OEIqZG
# /xjxucP3z0hCcpkaHv+cZos5nAHBqd1qlD9OWL+7CoC1xD7Cpnt5BsL4ctGtHp/e
# vmJz2s5DcK3vbn2V0O+ZioJYugGwscEJ7vJQStVoMiOTHrTURcYlozZWA7D/ARZg
# 1+PVtcNQpW+Wy/FbNkXd/4UuPM5JrXM6BbVL0XLd/uQT9uCJ35mjatyFoYNJxQTS
# 9ozXlDetp2LBe2a3Qz6pJ47zeh3Nn1Cozn9TKb6nQeotBsevKanCQJE4P3qolt2n
# /hS8uEroS0OslC5pDHH4RN0vJfkUqDSO6usbdQ6RDq2zytJ3Jh5jfx4/UR7ppD+L
# h6rhHXTVTYrzA4EbPSsXPTpYCwB31KCUnFuoes1e4uFshJLMZSXs9WsLie+Repv6
# XHJBci5qFThufhR0cp6HmMw8Z6cAt/QNp2QL1mUmNl0s3lZHKj5zGdQS01TKzXxT
# n8eWcpxhYtXtUHMXU+snTB4V+XRkE7IbUP3nNvhkMwVRO8xMAkFlnLxs/OJVzeIf
# 3nWTPBZQv89oRV+ZGXwP8h7t0Mp2V+KWdwr/k0i6JYxWnXSCCAXGasz48O40e9bw
# 3M97jbBtoeNrmpl+ouVVgY30X8LzHq3dBvpFJjjgbWncGZB/i5RYQ7926qxIha24
# m2VedsceQsecta4kfn+3GqGCF3YwghdyBgorBgEEAYI3AwMBMYIXYjCCF14GCSqG
# SIb3DQEHAqCCF08wghdLAgEDMQ8wDQYJYIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQ
# AQSgaARmMGQCAQEGCWCGSAGG/WwHATAxMA0GCWCGSAFlAwQCAQUABCAD1qpvpBYd
# x6FRk42q5rXbDkPVdQdcQ9ESla7/D8LTbQIQeZOd6k8oGiuFvvf4rU177hgPMjAy
# NjAxMTQwODA4MjlaoIITOjCCBu0wggTVoAMCAQICEAqA7xhLjfEFgtHEdqeVdGgw
# DQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0
# LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGlu
# ZyBSU0E0MDk2IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2MDQwMDAwMDBaFw0zNjA5
# MDMyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjE7MDkGA1UEAxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQwOTYgVGltZXN0YW1wIFJl
# c3BvbmRlciAyMDI1IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQ
# RqwtEsae0OquYFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ3xTWcfsLwOvRxUwXcGx8
# AUjni6bz52fGTfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqVQ+3bzWYesFtkepErvUSb
# f+EIYLkrLKd6qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjoT1FpS54dNApZfKY61HAl
# dytxNM89PZXUP/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R0V3Zp3DjjANwqAf4lEkT
# lCDQ0/fKJLKLkzGBTpx6EYevvOi7XOc4zyh1uSqgr6UnbksIcFJqLbkIXIPbcNmA
# 98Oskkkrvt6lPAw/p4oDSRZreiwB7x9ykrjS6GS3NR39iTTFS+ENTqW8m6THuOmH
# HjQNC3zbJ6nJ6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0dVVZw7knh1WZXOLHgDvu
# ndrAtuvz0D3T+dYaNcwafsVCGZKUhQPL1naFKBy1p6llN3QgshRta6Eq4B40h5av
# Mcpi54wm0i2ePZD5pPIssoszQyF4//3DoK2O65Uck5Wggn8O2klETsJ7u8xEehGi
# fgJYi+6I03UuT1j7FnrqVrOzaQoVJOeeStPeldYRNMmSF3voIgMFtNGh86w3ISHN
# m0IaadCKCkUe2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwIDAQABo4IBlTCCAZEwDAYD
# VR0TAQH/BAIwADAdBgNVHQ4EFgQU5Dv88jHt/f3X85FxYxlQQ89hjOgwHwYDVR0j
# BBgwFoAU729TSunkBnx6yuKQVvYv1Ensy04wDgYDVR0PAQH/BAQDAgeAMBYGA1Ud
# JQEB/wQMMAoGCCsGAQUFBwMIMIGVBggrBgEFBQcBAQSBiDCBhTAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMF0GCCsGAQUFBzAChlFodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBp
# bmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0fBFgwVjBUoFKgUIZOaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1w
# aW5nUlNBNDA5NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQC
# MAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAZSqt8RwnBLmuYEHs0QhE
# nmNAciH45PYiT9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZhY+hIfP2JkQ38U+wtJPB
# VBajYfrbIYG+Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/ciZmUnthfAEP1HShTrY+
# 2DE5qjzvZs7JIIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk6FxRPyUPxAAYH2Vy1lNM
# 4kzekd8oEARzFAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQUSntbjZ80FU3i54tpx5F
# /0Kr15zW/mJAxZMVBrTE2oi0fcI8VMbtoRAmaaslNXdCG1+lqvP4FbrQ6IwSBXkZ
# agHLhFU9HCrG/syTRLLhAezu/3Lr00GrJzPQFnCEH1Y58678IgmfORBPC1JKkYaE
# t2OdDh4GmO0/5cHelAK2/gTlQJINqDr6JfwyYHXSd+V08X1JUPvB4ILfJdmL+66G
# p3CSBXG6IwXMZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1qmcwbdUfcSYCn+OwncVUX
# f53VJUNOaMWMts0VlRYxe5nK+At+DI96HAlXHAL5SlfYxJ7La54i71McVWRP66bW
# +yERNpbJCjyCYG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhDBf3Froguzzhk++ami+r3
# Qrx5bIbY3TVzgiFI7Gq3zWcwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmG
# MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5
# NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8G
# A1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBT
# SEEyNTYgMjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0
# eDHTCphBcr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+Ruw
# OnPhof6pvF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4B
# t0mAxAHeHYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1U
# kxBvMgEdgkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTca
# arps0wjUjsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zb
# CclF83bRVFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnG
# pTXiUOeSLsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/
# AMOMCZIVNSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v
# 5ydPpOjL6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoi
# wOrUG2ZdSoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm
# 2qA+sdFUeEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYD
# VR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04w
# HwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGG
# MBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBD
# BgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNl
# cnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgB
# hv1sBwEwDQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Q
# h8WIGjB/T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3
# YTj+IQhQE7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQ
# wr8Myb9rEVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/
# wdG2th9y1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81
# hjajV/gxdEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00
# TYr2Lr3ty9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNj
# qFzeGxcytL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0
# cuJG7uEBYTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9
# sC+NJpud/v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0
# LckTetiSuEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2
# tszWkPZPubdcMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG
# 9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw
# FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1
# cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBi
# MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
# d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
# RzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAi
# MGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnny
# yhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE
# 5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm
# 7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5
# w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsD
# dV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1Z
# XUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS0
# 0mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hk
# pjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m8
# 00ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+i
# sX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB
# /zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReui
# r/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0w
# azAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUF
# BzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk
# SURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAG
# BgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9
# mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxS
# A8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/
# 6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSM
# b++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt
# 9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYIDfDCC
# A3gCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x
# QTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQw
# OTYgU0hBMjU2IDIwMjUgQ0ExAhAKgO8YS43xBYLRxHanlXRoMA0GCWCGSAFlAwQC
# AQUAoIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUx
# DxcNMjYwMTE0MDgwODI5WjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTdYjCshgot
# MGvaOLFoeVIwB/tBfjAvBgkqhkiG9w0BCQQxIgQgEGopmbf+oCdKIQ4SYn48VdmO
# KPXFNGUy6De3eYFH+0owNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgSqA/oizXXITF
# XJOPgo5na5yuyrM/420mmqM08UYRCjMwDQYJKoZIhvcNAQEBBQAEggIAINVRiY8Y
# cuxQgd/5NpL+9TvmFhquiqSuMjj6zabbVQMvTFX8xEaTb5M1fZpcnbQBDpPGXZzx
# u+b9rUKRuNuS3n01L/h19ATC4JSC1qMdlfpmhKm7SqCXbrNbz6qLf5BoDzKFDleC
# zCEJwKuLk8wxR0FTumPcsvi5GY8yGlQQPj5oAqWe3k+A4DvREOtM8GIiX0FFUMoN
# /lhpczTULfbLPSL6PADb4Wq5j4xfJpOe+m8nA8OssE87BGlnT83kmIPAaY3IUK3o
# vicFTeynKw7SzYPCFPC/X2SbOL+ESfffWhXv3X5d/yoJ9b0KSnFJ8BtgAk53/3et
# iRcD/DmwtS4T2BJ5ZQ662vlmm3kW24txRibNabI1LzYYMzZ77UWzflfAruVpzurs
# 0pgkublHOqCGdDb6aDGojgzyjhDLdIl6KLmaPmEMXVya38ZoEBxLPKEFJ2JtTuws
# sHfQUVl7MhMP/Tu1/1i1Lm+p3JozaUMHM54vF1OgPUCqZGN/BvYxWB0aqWGiEIlH
# 2nhndDMADeE44D1Yb39Viwu9epONRpG/vNGoyfE9Ur3QVxIDYgdCkbapT6ypzdmK
# RQKcbpacYATTJYenk5zSEEddiC7n5ppeh8bx65LprvmyuBf3RVY1a/abLdVF++fJ
# KT5/a6cFU41SATaP+xQ/x7blDj6YXmmUx0Q=
# SIG # End signature block