using CommunityToolkit.Mvvm.Input; using Harmonia.Core.Player; using Harmonia.Core.Playlists; using Harmonia.WinUI.Messaging; using Microsoft.UI.Dispatching; using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; namespace Harmonia.WinUI.ViewModels; public partial class PlaylistsViewModel : ViewModelBase { private readonly IPlaylistManager _playlistManager; private readonly IAudioPlayer _audioPlayer; private readonly IMessageService _messageService; private readonly DispatcherQueue _dispatcherQueue; private ObservableCollection _playlists = []; public ObservableCollection Playlists { get { return _playlists; } set { SetProperty(ref _playlists, value); } } private PlaylistItemViewModel? _selectedPlaylist = null; public PlaylistItemViewModel? SelectedPlaylist { get { return _selectedPlaylist; } set { if (SetProperty(ref _selectedPlaylist, value)) { _playlistManager.CurrentPlaylist = value?.Playlist; } } } private PlaylistItemViewModel? _activePlaylist = null; public PlaylistItemViewModel? ActivePlaylist { get { return _activePlaylist; } set { SetProperty(ref _activePlaylist, value); } } private PlaylistItemViewModel? _flyoutPlaylist = null; public PlaylistItemViewModel? FlyoutPlaylist { get { return _flyoutPlaylist; } set { SetProperty(ref _flyoutPlaylist, value); } } public IAsyncRelayCommand RenamePlaylistCommand { get; } public IRelayCommand LockPlaylistCommand { get; } public IRelayCommand UnlockPlaylistCommand { get; } public IAsyncRelayCommand DeletePlaylistCommand { get; } public PlaylistsViewModel(IPlaylistManager playlistManager, IAudioPlayer audioPlayer, IMessageService messageService) { _playlistManager = playlistManager; _playlistManager.PlaylistAdded += OnPlaylistAdded; _playlistManager.PlaylistRemoved += OnPlaylistRemoved; _playlistManager.CurrentPlaylistChanged += OnCurrentPlaylistChanged; _messageService = messageService; _audioPlayer = audioPlayer; _audioPlayer.PlayingSongChanged += OnPlayingSongChanged; _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); _playlists = new ObservableCollection(_playlistManager.Playlists.Select(p => new PlaylistItemViewModel(p))); _selectedPlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _playlistManager.CurrentPlaylist); _activePlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _audioPlayer.Playlist); RenamePlaylistCommand = new AsyncRelayCommand(RenamePlaylist); LockPlaylistCommand = new RelayCommand(LockPlaylist); UnlockPlaylistCommand = new RelayCommand(UnlockPlaylist); DeletePlaylistCommand = new AsyncRelayCommand(DeletePlaylistAsync); } private void OnCurrentPlaylistChanged(object? sender, EventArgs e) { SelectedPlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _playlistManager.CurrentPlaylist); } private void OnPlaylistAdded(object? sender, PlaylistAddedEventArgs e) { Playlists.Add(new PlaylistItemViewModel(e.Playlist)); } private void OnPlaylistRemoved(object? sender, PlaylistRemovedEventArgs e) { var playlistView = Playlists.FirstOrDefault(pv => pv.Playlist == e.Playlist); if (playlistView != null) { playlistView.Unsubscribe(); Playlists.Remove(playlistView); } } private void OnPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) { _dispatcherQueue.TryEnqueue(UpdateActivePlaylist); } private void UpdateActivePlaylist() { ActivePlaylist = Playlists.FirstOrDefault(pv => pv.Playlist == _audioPlayer.Playlist); } private async Task RenamePlaylist(PlaylistItemViewModel? playlistItem) { if (playlistItem is null || playlistItem.Playlist is null) return; Playlist playlist = playlistItem.Playlist; string newName = await _messageService.InputTextAsync( $"Rename Playlist - {playlist.Name}", "Enter a new name for the playlist:", playlist.Name ?? string.Empty); if (string.IsNullOrWhiteSpace(newName)) return; playlist.SetName(newName); } private void LockPlaylist(PlaylistItemViewModel? playlistItem) { if (playlistItem is null || playlistItem.Playlist is null) return; Playlist playlist = playlistItem.Playlist; playlist.Lock(); } private void UnlockPlaylist(PlaylistItemViewModel? playlistItem) { if (playlistItem is null || playlistItem.Playlist is null) return; Playlist playlist = playlistItem.Playlist; playlist.Unlock(); } private async Task DeletePlaylistAsync(PlaylistItemViewModel? playlistItem) { if (playlistItem is null || playlistItem.Playlist is null) return; Playlist playlist = playlistItem.Playlist; bool confirmed = await _messageService.ConfirmAsync($"Delete Playlist - {playlist.Name}", "Are you sure you want to delete this playlist?"); if (!confirmed) return; _playlistManager.RemovePlaylist(playlist); } }