using System; using System.Collections.Generic; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using FasdDesktopUi.Basics.Models; using C4IT.FASD.Cockpit.Communication; using C4IT.Logging; using static C4IT.Logging.cLogManager; using C4IT.MultiLanguage; using C4IT.FASD.Base; namespace FasdDesktopUi.Basics.UserControls { public partial class InformationClassSearchBar : UserControl, IBlurInvoker { #region Properties public enum eSearchStatus { message, active, fixedResult } public eSearchStatus SearchStatus { get; private set; } = eSearchStatus.message; private static CancellationTokenSource _currentSearchTaskToken = null; private static Guid? _currentSearchTaskId = null; private static readonly object _currentSearchTaskLock = new object(); private readonly Dictionary _searchIcons = null; public delegate Task ChangedSearchValueDelegate(cFilteredResults results); public ChangedSearchValueDelegate ChangedSearchValue { get; set; } = null; public Action CancledSearchAction { get; set; } public bool BlurInvoker_IsActive => IsVisible; public string SearchValue => InnerSearchBar.SearchValue; #endregion #region Dependency Properties public static readonly DependencyProperty SearchButtonSizeProperty = DependencyProperty.Register(nameof(SearchButtonSize), typeof(double), typeof(InformationClassSearchBar), new PropertyMetadata(30.0)); public double SearchButtonSize { get => (double)GetValue(SearchButtonSizeProperty); set => SetValue(SearchButtonSizeProperty, value); } public static readonly DependencyProperty CloseButtonSizeProperty = DependencyProperty.Register(nameof(CloseButtonSize), typeof(double), typeof(InformationClassSearchBar), new PropertyMetadata(30.0)); public double CloseButtonSize { get => (double)GetValue(CloseButtonSizeProperty); set => SetValue(CloseButtonSizeProperty, value); } #endregion public InformationClassSearchBar() { InitializeComponent(); _searchIcons = new Dictionary { { enumF4sdSearchResultClass.Phone, PhoneCallIndicator }, { enumF4sdSearchResultClass.User, UserCallIndicator }, { enumF4sdSearchResultClass.Computer, ComputerCallIndicator } }; } public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e) { BlurInvoker.InvokeVisibilityChanged(this, new EventArgs()); if (e.NewValue is bool newVisible) { if (!newVisible) { InnerSearchBar.IsInputEnabled = true; InnerSearchBar.ShowSearchButton = true; WarningIndicator.Visibility = Visibility.Collapsed; TicketOverview.Instance?.ResetSelection(); foreach (var entry in _searchIcons.Values) entry.Visibility = Visibility.Collapsed; } SetApiStatus(); } if (Visibility == Visibility.Visible) Dispatcher.BeginInvoke((Action)(() => InnerSearchBar.FocusInput()), DispatcherPriority.Render); } public void Clear() { SearchStatus = eSearchStatus.message; InnerSearchBar.Clear(); } public void ActivateManualSearch() { SearchStatus = eSearchStatus.active; InnerSearchBar.ShowSearchButton = true; WarningIndicator.Visibility = Visibility.Collapsed; foreach (var entry in _searchIcons.Values) entry.Visibility = Visibility.Collapsed; InnerSearchBar.Clear(); InnerSearchBar.IsInputEnabled = true; InnerSearchBar.FocusInput(); } public void SetSearchText(string search) { SearchStatus = eSearchStatus.active; InnerSearchBar.SetSearchText(search); } public void SetSpinnerVisibility(Visibility visibility) { InnerSearchBar.SetSpinnerVisibility(visibility); } public async Task SetFixedSearchResultAsync(enumF4sdSearchResultClass resultClass, string search, cFilteredResults result) { SearchStatus = eSearchStatus.fixedResult; InnerSearchBar.IsInputEnabled = false; InnerSearchBar.ShowSearchButton = false; WarningIndicator.Visibility = Visibility.Collapsed; foreach (var entryIcon in _searchIcons) entryIcon.Value.Visibility = entryIcon.Key == resultClass ? Visibility.Visible : Visibility.Collapsed; InnerSearchBar.SetSearchText(search); if (ChangedSearchValue != null) await ChangedSearchValue.Invoke(result); } public void SetApiStatus() { try { var status = cConnectionStatusHelper.Instance?.ApiConnectionStatus; if (status == null) return; bool isEnabled = false; string txt = null; switch (status) { case cConnectionStatusHelper.enumOnlineStatus.online: isEnabled = true; break; case cConnectionStatusHelper.enumOnlineStatus.connectionError: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ConnectError"); break; case cConnectionStatusHelper.enumOnlineStatus.incompatibleServerVersion: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IncompatibleVersion"); break; case cConnectionStatusHelper.enumOnlineStatus.serverStarting: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerStarting"); break; case cConnectionStatusHelper.enumOnlineStatus.serverNotConfigured: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerNotConfigured"); break; case cConnectionStatusHelper.enumOnlineStatus.illegalConfig: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IllegalConfig"); break; case cConnectionStatusHelper.enumOnlineStatus.unauthorized: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Unauthorized"); break; default: txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Offline"); break; } if (!isEnabled) { SearchStatus = eSearchStatus.message; InnerSearchBar.SetSearchText(txt); InnerSearchBar.IsInputEnabled = false; WarningIndicator.Visibility = Visibility.Visible; InnerSearchBar.ShowSearchButton = false; foreach (var entry in _searchIcons.Values) entry.Visibility = Visibility.Collapsed; } } catch (Exception e) { LogException(e); } } private async Task CancelRunningSearchTaskAsync() { lock (_currentSearchTaskLock) { if (_currentSearchTaskToken != null) { LogEntry("Canceling current running search..."); _currentSearchTaskToken.Cancel(true); _currentSearchTaskToken = null; } } Guid? currentTaskId = null; lock (_currentSearchTaskLock) { if (_currentSearchTaskId != null) { currentTaskId = _currentSearchTaskId; _currentSearchTaskId = null; } } if (currentTaskId != null) { LogEntry("Sending a search stop..."); await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStop((Guid)currentTaskId, CancellationToken.None); } } private async void InnerSearchBar_SearchValueChanged(object sender, string searchValue) { MethodBase cm = null; if (cLogManager.DefaultLogger.IsDebug) { cm = MethodBase.GetCurrentMethod(); LogMethodBegin(cm); } try { await CancelRunningSearchTaskAsync(); lock (_currentSearchTaskLock) { LogEntry("Start running new search..."); SearchValueChanged?.Invoke(this, searchValue); } } catch (Exception e) { LogException(e); } finally { if (cm != null) LogMethodEnd(cm); } } private void InnerSearchBar_CancelledSearch(object sender, RoutedEventArgs e) { e.Handled = true; RaiseCancledSearchEvent(); if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online) InnerSearchBar.Clear(); CancledSearchAction?.Invoke(); } #region Events public event EventHandler SearchValueChanged; public static readonly RoutedEvent CancledSearchEvent = EventManager.RegisterRoutedEvent(nameof(CancledSearch), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(InformationClassSearchBar)); public event RoutedEventHandler CancledSearch { add => AddHandler(CancledSearchEvent, value); remove => RemoveHandler(CancledSearchEvent, value); } private void RaiseCancledSearchEvent() { RaiseEvent(new RoutedEventArgs(CancledSearchEvent)); } #endregion } }