using System.Collections.ObjectModel; using System.Windows; using CommunityToolkit.Mvvm.ComponentModel; using HC_APTBS.Models; using HC_APTBS.Services; namespace HC_APTBS.ViewModels { /// /// Represents one row in the BIP-STATUS display. /// public sealed partial class BipRowViewModel : ObservableObject { /// Zero-based index of this BIP definition entry. public int Index { get; init; } /// 16-bit nibble pattern from the CFG (displayed as "0xXXXX"). public string HexPattern { get; init; } = string.Empty; /// Raw hex value — used to re-resolve the description on language change. public ushort RawHex { get; init; } /// SpecialFunction from the CFG — part of the localization key. public int SpecialFunction { get; init; } /// Original XML text, used as fallback when no resource key matches. public string FallbackDescription { get; init; } = string.Empty; /// Human-readable description shown on match; updated on language switch. [ObservableProperty] private string _description = string.Empty; /// HTML hex colour for the status indicator: green = inactive, red = match detected. [ObservableProperty] private string _color = "#26C200"; /// True when this BIP pattern currently matches the captured word. [ObservableProperty] private bool _isActive; } /// /// ViewModel for the BIP-STATUS display user control. /// /// /// Only populated for PSG5-PI pumps (those whose /// is non-null). When is false the view hides itself. /// /// public sealed partial class BipDisplayViewModel : ObservableObject { private readonly ILocalizationService _loc; // ── Properties ──────────────────────────────────────────────────────────── /// True when the current pump has BIP definitions; controls view visibility. [ObservableProperty] private bool _hasDefinition; /// Last raw BIP word received from the ECU (displayed as hex for diagnostics). [ObservableProperty] private string _rawValue = "–"; /// Ordered rows for the BIP definition table. public ObservableCollection Rows { get; } = new(); // ── Construction ────────────────────────────────────────────────────────── /// /// Initializes the view model and subscribes to language-change notifications /// so that row descriptions update automatically when the operator switches language. /// public BipDisplayViewModel(ILocalizationService loc) { _loc = loc; _loc.LanguageChanged += RefreshDescriptions; } // ── Public API ──────────────────────────────────────────────────────────── /// /// Loads the BIP definition for the selected pump and resets the display. /// Pass to hide the control (non-PSG5-PI pump selected). /// Must be called on the UI thread. /// public void LoadDefinition(PumpBipDefinition? bipDef) { Rows.Clear(); RawValue = "–"; if (bipDef == null || bipDef.Bits.Count == 0) { HasDefinition = false; return; } foreach (var d in bipDef.Bits) { Rows.Add(new BipRowViewModel { Index = d.Index, HexPattern = $"0x{d.HexPattern:X4}", RawHex = d.HexPattern, SpecialFunction = d.SpecialFunction, FallbackDescription = d.Description, Description = ResolveDescription(d.HexPattern, d.SpecialFunction, d.Description), Color = "#26C200", IsActive = false }); } HasDefinition = true; } /// /// Updates the display with a newly captured BIP status word. /// Marks matching (and enabled) rows as active. /// Must be called on the UI thread. /// /// Current pump's BIP definition. /// Raw 16-bit value read from ECU RAM 0x0106. public void UpdateBipWord(PumpBipDefinition bipDef, ushort rawWord) { RawValue = $"0x{rawWord:X4}"; for (int i = 0; i < Rows.Count && i < bipDef.Bits.Count; i++) { var def = bipDef.Bits[i]; var row = Rows[i]; // Bitmask match: all pattern bits must be set in rawWord. bool matches = def.Enabled && (rawWord & def.HexPattern) == def.HexPattern; row.IsActive = matches; row.Color = matches ? "#FF1E1E" : "#26C200"; } } /// Resets all rows to inactive / green without clearing the definitions. public void Reset() { foreach (var row in Rows) { row.IsActive = false; row.Color = "#26C200"; } RawValue = "–"; } // ── Helpers ─────────────────────────────────────────────────────────────── /// /// Returns the localized description for a BIP entry keyed by (hex, specialFunction), /// falling back to the raw XML text when no resource key is found. /// private static string ResolveDescription(ushort hex, int sf, string fallback) { var key = $"Pump.Bip.Desc.{hex:X4}.{sf}"; return Application.Current.Resources[key]?.ToString() ?? fallback; } /// /// Re-resolves all row descriptions against the now-active resource dictionary. /// Called by . /// private void RefreshDescriptions() { foreach (var row in Rows) row.Description = ResolveDescription(row.RawHex, row.SpecialFunction, row.FallbackDescription); } } }