using C4IT.F4SD.DisplayFormatting; using C4IT.FASD.Base; using C4IT.FASD.Cockpit.Communication; using C4IT.Logging; using C4IT.MultiLanguage; using FasdDesktopUi.Basics.Models; using FasdDesktopUi.Basics.UserControls; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using static C4IT.FASD.Base.cF4SDHealthCardRawData; using static C4IT.Logging.cLogManager; namespace FasdDesktopUi.Basics.UiActions { public class cShowDetailedDataAction : cUiActionBase { private static readonly Dictionary> CachedDetails = new Dictionary>(); private cSupportCaseDataProvider DataProvider; private readonly cHealthCardStateBase StateDefinition; private int DayIndex { get; set; } private string DetailsTitle { get; set; } private string Recommendation { get; set; } private cHealthCardDetailsTable ValuedDetailsData = null; public cShowDetailedDataAction(cHealthCardStateBase StateDefinition, int DayIndex = 0, cHealthCardDetailsTable ValuedDetailsData = null) { this.StateDefinition = StateDefinition; this.DayIndex = DayIndex; this.DetailsTitle = StateDefinition.Names.GetValue(); this.Recommendation = StateDefinition.Descriptions.GetValue(); if (this.Recommendation == String.Empty) this.Recommendation = null; this.ValuedDetailsData = ValuedDetailsData; } public override async Task RunUiActionAsync(object sender, UIElement UiLocation, bool isDetailedLayout, cSupportCaseDataProvider dataProvider) { try { if (!(UiLocation is Decorator decorator)) return false; DataProvider = dataProvider; DataProvider.HealthCardDataHelper.LoadingHelper.DataRefreshed += (s, e) => CachedDetails.Clear(); Mouse.OverrideCursor = Cursors.Wait; if (StateDefinition.Details is cHealthCardDetailsValued) { if (ValuedDetailsData == null) return false; } else { if (!await LoadDetailsDataAsync()) return false; } cDetailedDataModel detailedData = null; cDetailedChartModel detailedChartData = null; cChartModel chartData = null; if (StateDefinition.Details is cHealthCardDetailsValued) { detailedData = GetValuedDataModel(); } else { detailedData = GetDetailedData(); detailedChartData = GetDetailedChartData(); chartData = GetChartData(); } cRecommendationDataModel recommendationDataModel = Recommendation != null ? new cRecommendationDataModel() { Category = DetailsTitle, Recommendation = Recommendation } : null; if (decorator.Child is DataCanvas existingDataCanvas) { var tempDataCanvasData = new cDataCanvasDataModel() { QuickActionStatusMonitorData = null, DetailedData = detailedData, DetailedChartData = detailedChartData, ChartData = chartData, RecommendationData = recommendationDataModel }; if (!(StateDefinition.Details is cHealthCardDetailsValued)) { tempDataCanvasData.GetDetailedDataAsync = GetRefreshedDetailedDataAsync; tempDataCanvasData.GetChartDataAsync = GetRefreshedChartDataAsync; tempDataCanvasData.GetDatailedChartDataAsync = GetRefreshedDetailsChartDataAsync; } existingDataCanvas.DataCanvasData = tempDataCanvasData; existingDataCanvas.IsDetailedLayout = isDetailedLayout; existingDataCanvas.DataProvider = DataProvider; existingDataCanvas.Visibility = Visibility.Visible; } else { DataCanvas dataCanvas = new DataCanvas() { DataCanvasData = new cDataCanvasDataModel() { DetailedData = detailedData, DetailedChartData = detailedChartData, ChartData = chartData, RecommendationData = recommendationDataModel }, IsDetailedLayout = isDetailedLayout, DataProvider = DataProvider }; if (!(StateDefinition.Details is cHealthCardDetailsValued)) { dataCanvas.DataCanvasData.GetDetailedDataAsync = GetRefreshedDetailedDataAsync; dataCanvas.DataCanvasData.GetChartDataAsync = GetRefreshedChartDataAsync; dataCanvas.DataCanvasData.GetDatailedChartDataAsync = GetRefreshedDetailsChartDataAsync; } decorator.Child = dataCanvas; } decorator.Visibility = Visibility.Visible; return true; } catch (Exception E) { LogException(E); } finally { Mouse.OverrideCursor = null; } return false; } private async Task LoadDetailsDataAsync() { try { if (StateDefinition == null || StateDefinition.Details == null) return false; if (!(StateDefinition.Details is cHealthCardDetails _details) || _details.Table == null) return false; if (CachedDetails.TryGetValue(DataProvider.Identities, out var cachedDetailsForIdentities)) { if (cachedDetailsForIdentities.TryGetValue(_details.Table, out _)) return true; } else cachedDetailsForIdentities = new Dictionary(); cF4sdHealthCardRawDataRequest requestData = new cF4sdHealthCardRawDataRequest() { Identities = DataProvider.Identities, MaxAge = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge, Tables = StateDefinition.GetRequiredTables() }; var detailsData = await cFasdCockpitCommunicationBase.Instance.GetDetailsData(requestData); if (detailsData.Any(data => data.Name == _details.Table) || detailsData.Any(data => data.Name == StateDefinition.DetailedChartDetails?.ValueTable) || detailsData.Any(data => data.Name == StateDefinition.ChartDetails?.ValueTable)) { if (StateDefinition.Details != null && detailsData.Any(data => data.Name == _details.Table)) { if (!cachedDetailsForIdentities.ContainsKey(_details.Table)) cachedDetailsForIdentities.Add(_details.Table, detailsData.First(data => data.Name == _details.Table)); if (!CachedDetails.ContainsKey(DataProvider.Identities)) CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities); } if (StateDefinition.DetailedChartDetails != null && detailsData.Any(data => data.Name == StateDefinition.DetailedChartDetails.ValueTable)) { if (!cachedDetailsForIdentities.ContainsKey(StateDefinition.DetailedChartDetails.ValueTable)) cachedDetailsForIdentities.Add(StateDefinition.DetailedChartDetails.ValueTable, detailsData.First(data => data.Name == StateDefinition.DetailedChartDetails.ValueTable)); if (!CachedDetails.ContainsKey(DataProvider.Identities)) CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities); } if (StateDefinition.ChartDetails != null && detailsData.Any(data => data.Name == StateDefinition.ChartDetails.ValueTable)) { if (!cachedDetailsForIdentities.ContainsKey(StateDefinition.ChartDetails.ValueTable)) cachedDetailsForIdentities.Add(StateDefinition.ChartDetails.ValueTable, detailsData.First(data => data.Name == StateDefinition.ChartDetails.ValueTable)); if (!CachedDetails.ContainsKey(DataProvider.Identities)) CachedDetails.Add(DataProvider.Identities, cachedDetailsForIdentities); } } else return false; return true; } catch (Exception E) { LogException(E); } return false; } private void UpdateProcessorStateDefinition() { // correct an error in older definitions of table agnt-computer-event-details-processorUsage try { var oldFromColumn = StateDefinition.Details.FirstOrDefault(column => column.Name == "From"); var oldToColumn = StateDefinition.Details.FirstOrDefault(column => column.Name == "To"); if (oldFromColumn is null || oldToColumn is null) return; if (oldFromColumn.Column != "Duration" || oldToColumn.Column != "time") return; oldFromColumn.Column = "time"; oldToColumn.Column = "Duration.add"; } catch (Exception E) { LogException(E); } } private void ProcessDetailValue(string processintType, ref object rawValue, DateTime timeColumnValue) { try { if (rawValue is Int64 milliSec) { switch (processintType) { case "add": rawValue = timeColumnValue.AddMilliseconds(milliSec); break; case "sub": rawValue = timeColumnValue.AddMilliseconds(-milliSec); break; } } } catch (Exception E) { LogException(E); } } private cDetailedDataModel GetValuedDataModel() { if (!(StateDefinition.Details is cHealthCardDetailsValued _details) || ValuedDetailsData == null) return null; if (ValuedDetailsData.Columns.Count > 1) return null; var _rowHeadings = _details.Select(v => v.Names.GetValue() as object).ToList(); cDetailedDataModel output = new cDetailedDataModel() { Heading = StateDefinition.Names.GetValue(), FullDetailedData = new List(), HasColumnHeaders = _rowHeadings.Count > 1 }; if (_rowHeadings.Count > 1) output.FullDetailedData.Add(_rowHeadings); var _data = ValuedDetailsData.Values[0]; foreach (var _row in _data) output.FullDetailedData.Add(new List() { _row[0] }); return output; } private cDetailedDataModel GetDetailedData() { try { const string timeColumnName = "time"; cDetailedDataModel output = new cDetailedDataModel() { FullDetailedData = new List() }; string dateAddtionFormat = cMultiLanguageSupport.GetItem("DetailsPage.History.Details"); string dateAddition = string.Format(dateAddtionFormat, DateTime.Today.AddDays(-DayIndex).ToString("d", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage))); string detailedDataHeading = "Details - " + DetailsTitle + dateAddition; output.Heading = detailedDataHeading; if (!(StateDefinition.Details is cHealthCardDetails _details) || _details.Table == null) return null; // correct an error in older definitions of table agnt-computer-event-details-processorUsage if (_details.Table == "agnt-computer-event-details-processorUsage") UpdateProcessorStateDefinition(); var headerValues = StateDefinition.Details.Select(value => value.Names.GetValue()); output.FullDetailedData.Add(headerValues.ToList()); var detailsData = CachedDetails[DataProvider.Identities][_details.Table]; if (!detailsData.Values.TryGetValue(DayIndex, out var details)) return output; int columnCount = StateDefinition.Details.Count; List rawColumnIndexes = new List(columnCount); List displayTypes = new List(columnCount); List valueProcessings = new List(columnCount); int timeColumnIndex = detailsData.Columns.IndexOf(timeColumnName); int filterColumnIndex = detailsData.Columns.IndexOf(StateDefinition.Details?.Filter?.FilterColumn); foreach (var columnDefinition in StateDefinition.Details) { var splitColumnName = columnDefinition.Column.Split('.'); var rawColumnIndex = detailsData.Columns.IndexOf(splitColumnName[0]); var displayType = columnDefinition.DisplayType; var valueProcessing = splitColumnName.Length > 1 ? splitColumnName[1] : null; rawColumnIndexes.Add(rawColumnIndex); displayTypes.Add(cUtility.GetRawValueType(displayType)); valueProcessings.Add(valueProcessing); } foreach (var detailsRow in details) { var displayValuesOfRow = new List(columnCount); var displayTypeEnumerator = displayTypes.GetEnumerator(); var valueProcessingsEnumerator = valueProcessings.GetEnumerator(); bool shouldHideRow = false; if (StateDefinition.Details.Filter != null && !rawColumnIndexes.Contains(filterColumnIndex)) { bool columnValueMatchesFilterValue = StateDefinition.Details.Filter.FilterValues.Contains(detailsRow[filterColumnIndex]); if (!columnValueMatchesFilterValue) shouldHideRow = true; } cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)); foreach (var index in rawColumnIndexes) { try { if (shouldHideRow) continue; if (detailsRow.Length < index || !displayTypeEnumerator.MoveNext() || !valueProcessingsEnumerator.MoveNext()) continue; var rawDetailValue = detailsRow[index]; if (index == filterColumnIndex && !StateDefinition.Details.Filter.FilterValues.Contains(rawDetailValue)) { shouldHideRow = true; continue; } if (valueProcessingsEnumerator.Current != null) if (detailsRow[timeColumnIndex] is DateTime timeColumnValue) ProcessDetailValue(valueProcessingsEnumerator.Current, ref rawDetailValue, timeColumnValue); var displayValue = cUtility.RawValueFormatter.GetDisplayValue(rawDetailValue, displayTypeEnumerator.Current); displayValuesOfRow.Add(displayValue); } catch (Exception E) { LogException(E); } } if (shouldHideRow) continue; output.FullDetailedData.Add(displayValuesOfRow); } return output; } catch (Exception E) { LogException(E); } return null; } private cDetailedChartModel GetDetailedChartData() { try { if (StateDefinition?.DetailedChartDetails is null) return null; var detailsDataTable = CachedDetails[DataProvider.Identities][StateDefinition.DetailedChartDetails.ValueTable]; int valueIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.ValueColumn); int timeIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.TimeColumn); int durationIndex = detailsDataTable.Columns.IndexOf(StateDefinition.DetailedChartDetails.DurationColumn); string title = StateDefinition.Names.GetValue(); bool isThresholdActive = StateDefinition is cHealthCardStateLevel; var output = new cDetailedChartModel() { Data = detailsDataTable.Values[DayIndex], ValueIndex = valueIndex, TimeIndex = timeIndex, DurationIndex = durationIndex, ChartTitle = title, IsThresholdActive = isThresholdActive, }; if (StateDefinition is cHealthCardStateLevel stateLevelDefinition) { output.WarningThreshold = stateLevelDefinition.Warning; output.ErrorThreshold = stateLevelDefinition.Error; } return output; } catch (Exception E) { LogException(E); } return null; } private cChartModel GetChartData() { try { if (StateDefinition?.ChartDetails is null) return null; var detailsDataTable = CachedDetails[DataProvider.Identities][StateDefinition.ChartDetails.ValueTable]; int valueIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.ValueColumn); int timeIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.TimeColumn); int durationIndex = detailsDataTable.Columns.IndexOf(StateDefinition.ChartDetails.DurationColumn); string title = StateDefinition.Names.GetValue(); bool isThresholdActive = false; double warningThreshold = 0; double errorThreshold = 0; bool isDirectionUp = true; if (StateDefinition is cHealthCardStateLevel stateLevel) { isThresholdActive = true; warningThreshold = stateLevel.Warning; errorThreshold = stateLevel.Error; isDirectionUp = stateLevel.IsDirectionUp; } int stepLengthScale = StateDefinition.ChartDetails.StepLengthScale; int stepLengthLine = StateDefinition.ChartDetails.StepLengthLine; int maxValue = StateDefinition.ChartDetails.MaxValue; int minValue = StateDefinition.ChartDetails.MinValue; string unitFormat = StateDefinition.UnitFormat; var output = new cChartModel() { Data = detailsDataTable.Values[DayIndex], ValueIndex = valueIndex, TimeIndex = timeIndex, DurationIndex = durationIndex, ChartTitle = title, WarningThreshold = warningThreshold, ErrorThreshold = errorThreshold, IsThresholdActive = isThresholdActive, IsDirectionUp = isDirectionUp, StepLengthScale = stepLengthScale, StepLengthLine = stepLengthLine, MaxValue = maxValue, MinValue = minValue, UnitFormat = unitFormat, }; return output; } catch (Exception E) { LogException(E); } return null; } private async Task GetRefreshedDetailedDataAsync() { cDetailedDataModel output = null; try { CachedDetails.Remove(DataProvider.Identities); if (await LoadDetailsDataAsync()) return GetDetailedData(); } catch (Exception E) { LogException(E); } return output; } private async Task GetRefreshedDetailsChartDataAsync() { cDetailedChartModel output = null; try { CachedDetails.Remove(DataProvider.Identities); if (await LoadDetailsDataAsync()) return GetDetailedChartData(); } catch (Exception E) { LogException(E); } return output; } private async Task GetRefreshedChartDataAsync() { cChartModel output = null; try { CachedDetails.Remove(DataProvider.Identities); if (await LoadDetailsDataAsync()) return GetChartData(); } catch (Exception E) { LogException(E); } return output; } } }