using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using Avalonia.Collections; using Nito.Disposables.Internals; using StabilityMatrix.Avalonia.Helpers; using StabilityMatrix.Avalonia.Models; using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Avalonia.ViewModels.Inference; public abstract class StackViewModelBase : LoadableViewModelBase { private readonly ServiceManager vmFactory; // private readonly Dictionary> viewModelManager = new(); public AdvancedObservableList Cards { get; } = new(); protected StackViewModelBase(ServiceManager vmFactory) { this.vmFactory = vmFactory; Cards.CollectionChanged += (sender, args) => { if (args.NewItems != null) { var itemIndex = args.NewStartingIndex; foreach (var item in args.NewItems.OfType()) { item.OnContainerIndexChanged(itemIndex); itemIndex++; } } }; } public virtual void OnContainerIndexChanged(int value) { } /// /// Event raised when a card is added /// public event EventHandler? CardAdded; protected virtual void OnCardAdded(LoadableViewModelBase item) { CardAdded?.Invoke(this, item); } public void AddCards(params LoadableViewModelBase[] cards) { AddCards((IEnumerable)cards); } /// /// Register new cards /// public void AddCards(IEnumerable cards) { foreach (var card in cards) { Cards.Add(card); OnCardAdded(card); } } /// /// Registers new cards and returns self /// public StackViewModelBase WithCards(IEnumerable cards) { AddCards(cards); return this; } /// /// Gets a card by type at specified index /// public T GetCard(int index = 0) where T : LoadableViewModelBase { return Cards.OfType().ElementAtOrDefault(index) ?? throw new InvalidOperationException( $"Card of type {typeof(T).Name} at index {index} not found" ); } public void Clear() { Cards.Clear(); // viewModelManager.Clear(); } /// public override void LoadStateFromJsonObject(JsonObject state) { Clear(); var derivedTypes = ViewModelSerializer.GetDerivedTypes(typeof(LoadableViewModelBase)); if ( !state.TryGetPropertyValue("$values", out var values) || values is not JsonArray nodesArray ) { return; } foreach (var node in nodesArray.Select(n => n as JsonObject).WhereNotNull()) { // Get $type key if ( !node.TryGetPropertyValue("$type", out var typeValue) || typeValue is not JsonValue jsonValue || jsonValue.ToString() is not { } typeKey ) { continue; } // Get type from key if (!derivedTypes.TryGetValue(typeKey, out var type)) { continue; } if (vmFactory.Get(type) is not LoadableViewModelBase vm) { continue; } vm.LoadStateFromJsonObject(node); AddCards(vm); } } /// public override JsonObject SaveStateToJsonObject() { var derivedTypeNames = ViewModelSerializer .GetDerivedTypes(typeof(LoadableViewModelBase)) .ToDictionary(x => x.Value, x => x.Key); var nodes = new JsonArray( Cards .Select(x => { var typeKey = derivedTypeNames[x.GetType()]; var node = x.SaveStateToJsonObject(); node.Add("$type", typeKey); return (JsonNode)node; }) .ToArray() ); return new JsonObject { ["$values"] = nodes }; } }