// Copyright (c) Arlo Godfrey. All Rights Reserved. // Licensed under the GNU Lesser General Public License, Version 3.0 with additional terms. // See the LICENSE, LICENSE.LESSER and LICENSE.ADDITIONAL files in the project root for more information. using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using OwlCore.Events; using OwlCore.Extensions; using StrixMusic.Sdk.AdapterModels; using StrixMusic.Sdk.AppModels; using StrixMusic.Sdk.CoreModels; namespace StrixMusic.Sdk.ViewModels; /// /// A ViewModel wrapper for an instance of . /// public class StrixDataRootViewModel : ObservableObject, IStrixDataRoot { private readonly IStrixDataRoot _dataRoot; private readonly ObservableCollection _devices; /// /// Initializes a new instance of the class. /// public StrixDataRootViewModel(IStrixDataRoot dataRoot) { _dataRoot = dataRoot; Library = new LibraryViewModel(dataRoot.Library); if (dataRoot.Pins is not null) Pins = new PlayableCollectionGroupViewModel(dataRoot.Pins); if (dataRoot.RecentlyPlayed is not null) RecentlyPlayed = new RecentlyPlayedViewModel(dataRoot.RecentlyPlayed); if (dataRoot.Discoverables is not null) Discoverables = new DiscoverablesViewModel(dataRoot.Discoverables); if (dataRoot.Search is not null) Search = new SearchViewModel(dataRoot.Search); _devices = new ObservableCollection(dataRoot.Devices.Select(x => new DeviceViewModel(x))); AttachEvents(dataRoot); } private void AttachEvents(IStrixDataRoot dataRoot) { dataRoot.DevicesChanged += OnDevicesChanged; dataRoot.PinsChanged += OnPinsChanged; dataRoot.RecentlyPlayedChanged += OnRecentlyPlayedChanged; dataRoot.DiscoverablesChanged += OnDiscoverablesChanged; dataRoot.SearchChanged += OnSearchChanged; } private void DetachEvents(IStrixDataRoot dataRoot) { dataRoot.DevicesChanged -= OnDevicesChanged; dataRoot.PinsChanged -= OnPinsChanged; dataRoot.RecentlyPlayedChanged -= OnRecentlyPlayedChanged; dataRoot.DiscoverablesChanged -= OnDiscoverablesChanged; dataRoot.SearchChanged -= OnSearchChanged; } private void OnDevicesChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) { var wrappedAdded = addedItems.Select(x => new CollectionChangedItem(new DeviceViewModel(x.Data), x.Index)).ToList(); var wrappedRemoved = removedItems.Select(x => new CollectionChangedItem(new DeviceViewModel(x.Data), x.Index)).ToList(); _devices.ChangeCollection(wrappedAdded, wrappedRemoved); DevicesChanged?.Invoke(this, wrappedAdded, wrappedRemoved); } private void OnDiscoverablesChanged(object sender, IDiscoverables e) { Discoverables = new DiscoverablesViewModel(e); DiscoverablesChanged?.Invoke(this, Discoverables); } private void OnRecentlyPlayedChanged(object sender, IRecentlyPlayed e) { RecentlyPlayed = new RecentlyPlayedViewModel(e); RecentlyPlayedChanged?.Invoke(this, RecentlyPlayed); } private void OnPinsChanged(object sender, IPlayableCollectionGroup e) { Pins = new PlayableCollectionGroupViewModel(e); PinsChanged?.Invoke(this, Pins); } private void OnSearchChanged(object sender, ISearch e) { Search = new SearchViewModel(e); SearchChanged?.Invoke(this, Search); } /// public event EventHandler? SourcesChanged { add => _dataRoot.SourcesChanged += value; remove => _dataRoot.SourcesChanged -= value; } /// public event CollectionChangedEventHandler? DevicesChanged; /// public IReadOnlyList Sources => _dataRoot.Sources; /// public Task InitAsync(CancellationToken cancellationToken = new CancellationToken()) => _dataRoot.InitAsync(cancellationToken); /// public bool IsInitialized => _dataRoot.IsInitialized; /// public MergedCollectionConfig MergeConfig => _dataRoot.MergeConfig; /// public IReadOnlyList Devices => _devices; /// public ILibrary Library { get; } /// public IPlayableCollectionGroup? Pins { get; private set; } /// public ISearch? Search { get; private set; } /// public IRecentlyPlayed? RecentlyPlayed { get; private set; } /// public IDiscoverables? Discoverables { get; private set; } /// public event EventHandler? PinsChanged; /// public event EventHandler? DiscoverablesChanged; /// public event EventHandler? SearchChanged; /// public event EventHandler? RecentlyPlayedChanged; /// public bool Equals(ICore other) => _dataRoot.Equals(other); /// public ValueTask DisposeAsync() { DetachEvents(_dataRoot); return _dataRoot.DisposeAsync(); } }