using C4IT.FASD.Base; using C4IT.Logging; using C4IT.MultiLanguage; using FasdDesktopUi.Basics.Enums; using FasdDesktopUi.Basics.Services.RelationService; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using static C4IT.Logging.cLogManager; namespace FasdDesktopUi.Basics.UiActions { public class cUiProcessSearchResultAction : cUiActionBase { private readonly ISearchUiProvider _searchUiProvider; private readonly List _searchResults; private readonly List _loadedRelations = new List(); private readonly TaskCompletionSource _isSearchUnambigous = new TaskCompletionSource(); private IRelationService _relationService = null; public cF4sdApiSearchResultRelation PreSelectedSearchRelation { get; set; } = null; public cUiProcessSearchResultAction(string name, ISearchUiProvider searchUiProvider, List searchResults) { Name = name; _searchUiProvider = searchUiProvider; _searchResults = searchResults; _searchUiProvider.SearchService.RelationsFound += HandleRelationsFound; } ~cUiProcessSearchResultAction() { _searchUiProvider.SearchService.RelationsFound -= HandleRelationsFound; } /// If the search is unfinished. /// False: search is finished. /// True: search is ongoing. public override async Task RunUiActionAsync(object sender, UIElement uiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (dataProvider != null) { Debug.Assert(true, "At this moment, we want to create a new support call, so we must not have a dataProvider"); LogEntry("At this moment, we want to create a new support call, so we must not have a dataProvider", LogLevels.Error); return false; } return await ProcessSearchResultDefaultAsync(CancellationToken.None); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return false; } /// If the search is unfinished. /// False: search is finished. /// True: search is ongoing. private async Task ProcessSearchResultDefaultAsync(CancellationToken token) { try { if (_searchResults is null || _searchResults.Count <= 0) return false; _searchUiProvider.ShowLoadingTextItem(cMultiLanguageSupport.GetItem("Searchbar.Loading.Relations")); cF4sdStagedSearchResultRelationTaskId gatherRelationTask = await _searchUiProvider.SearchService.LoadRelationsAsync(_searchResults, token); HashSet orderedPendingInfoClasses = GetInformationClassOrderedByPriority(gatherRelationTask.PendingInformationClasses, cF4sdIdentityEntry.GetFromSearchResult(_searchResults.FirstOrDefault()?.Type ?? enumF4sdSearchResultClass.Unknown)); _searchUiProvider.SetPendingInformationClasses(orderedPendingInfoClasses); Mouse.OverrideCursor = null; if (MatchPreselectedSearchRelation(_loadedRelations)) return await ProcessSearchResultRelationAsync(_searchResults.First().Name, _loadedRelations, PreSelectedSearchRelation); if (await _isSearchUnambigous.Task) return await ProcessSearchResultRelationAsync(_searchResults.First().Name, _loadedRelations, _loadedRelations.FirstOrDefault()); return true; } catch (Exception ex) { LogException(ex); } return false; bool MatchPreselectedSearchRelation(IEnumerable relations) { if (PreSelectedSearchRelation is null || relations is null) return false; return relations.Any(entry => entry.Type == PreSelectedSearchRelation.Type && entry.id == PreSelectedSearchRelation.id); } } private async Task ProcessSearchResultRelationAsync(string name, List caseRelations, cF4sdApiSearchResultRelation selectedRelation) { var relationSearchResult = new cSearchHistorySearchResultEntry(_searchResults.FirstOrDefault().DisplayName, _searchResults.FirstOrDefault().DisplayName, _searchResults, caseRelations, _searchUiProvider); string displayName = !string.IsNullOrWhiteSpace(selectedRelation?.Name) ? $"{name} → {selectedRelation.Name}" : name; cUiProcessSearchRelationAction action = new cUiProcessSearchRelationAction(displayName, _searchResults, caseRelations, selectedRelation, _searchUiProvider, relationSearchResult, _relationService) { DisplayType = enumActionDisplayType.enabled, }; return await action.RunUiActionAsync(this, null, false, null); } private HashSet GetInformationClassOrderedByPriority(HashSet informationClasses, enumFasdInformationClass? excludedInformationClass = null) { try { var informationClassPrio = cFasdCockpitConfig.Instance.Global.InformationClassSearchPriority; if (excludedInformationClass.HasValue) informationClasses.Remove(excludedInformationClass.Value); if (informationClassPrio is null || informationClassPrio.Count == 0) return informationClasses; return informationClasses .OrderBy(infoClass => informationClassPrio.Contains(infoClass) ? informationClassPrio.IndexOf(infoClass) : int.MaxValue) .ToHashSet(); } catch (Exception ex) { LogException(ex); } return informationClasses; } private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e) { try { _loadedRelations.AddRange(e.StagedResultRelations.Relations); _relationService = e.RelationService; if (!e.StagedResultRelations.IsComplete) return; bool isSearchResultUnambigous = _loadedRelations.Count <= 1; if (_loadedRelations.Count == 0) _loadedRelations.Add(new cF4sdApiSearchResultRelation(_searchResults.FirstOrDefault())); _isSearchUnambigous.TrySetResult(isSearchResultUnambigous); } catch (Exception ex) { LogException(ex); } } } }