using System; using System.Collections; using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using HC_APTBS.Models; namespace HC_APTBS.ViewModels { /// /// Represents the state of a single bit indicator in the 16-bit pump status word display. /// public sealed class BitIndicatorViewModel : ObservableObject { [System.Runtime.CompilerServices.CompilerGenerated] private string _color = "#26C200"; /// HTML hex colour for the indicator background (e.g. "#26C200" = green, "#FF1E1E" = red). public string Color { get => _color; set => SetProperty(ref _color, value); } [System.Runtime.CompilerServices.CompilerGenerated] private string _description = string.Empty; /// Tooltip / label for this bit's current state. public string Description { get => _description; set => SetProperty(ref _description, value); } [System.Runtime.CompilerServices.CompilerGenerated] private bool _isActive; /// True when this bit is set in the status word. public bool IsActive { get => _isActive; set => SetProperty(ref _isActive, value); } /// Zero-based bit position (0–15) shown as a label beneath the indicator. public int Index { get; init; } } /// /// ViewModel for the StatusDisplay user control. /// /// /// Maintains a 16-element collection of objects, /// one per bit of the pump status word. Call whenever /// a new value arrives from the CAN bus. /// /// public sealed partial class StatusDisplayViewModel : ObservableObject { // ── Properties ──────────────────────────────────────────────────────────── /// Title shown above the bit display (e.g. "Table 2 – Status"). [ObservableProperty] private string _title = "STATUS"; /// 16 bit indicators for bits 0–15 of the current status word. public ObservableCollection Bits { get; } = new(); /// /// Fired when a bit that is flagged as an error transitions to active. /// The argument is the bit position (0-based). /// public event Action? ErrorBitDetected; // ── Constructor ─────────────────────────────────────────────────────────── /// Initialises the collection with 16 green indicator placeholders. public StatusDisplayViewModel() { for (int i = 0; i < 16; i++) Bits.Add(new BitIndicatorViewModel { Color = "#26C200", Description = $"Bit {i}", Index = i }); } // ── Public API ──────────────────────────────────────────────────────────── /// /// Updates all 16 bit indicators from a and a live value. /// Must be called on the UI thread. /// /// Definition describing what each bit means. /// Integer value from the pump CAN status parameter. public void UpdateStatusWord(PumpStatusDefinition statusDefinition, int rawValue) { if (statusDefinition == null) return; Title = $"Table {statusDefinition.Id} – {statusDefinition.Name}"; var bits = new BitArray(new[] { rawValue }); foreach (var statusBit in statusDefinition.Bits) { int index = statusBit.Bit; if (index < 0 || index >= 16) continue; bool isSet = index < bits.Length && bits[index]; var indicator = Bits[index]; indicator.IsActive = isSet; // Find the matching state definition and apply its colour/description. foreach (var val in statusBit.Values) { int expectedState = isSet ? 1 : 0; if (val.State == expectedState) { indicator.Color = "#" + val.Color; indicator.Description = val.Description; break; } } // Notify the bench service / main VM of error bits. if (isSet && statusBit.Enabled) ErrorBitDetected?.Invoke(index); } } /// Resets all indicators to the default green / inactive state. public void Reset() { for (int i = 0; i < Bits.Count; i++) { Bits[i].IsActive = false; Bits[i].Color = "#26C200"; Bits[i].Description = $"Bit {i}"; } } } }