namespace Harmonia.Core.Playlists; public class PlaylistManager : IPlaylistManager { private readonly IPlaylistRepository playlistRepository; private readonly List _playlists = []; private readonly Dictionary _playlistsBySongUid = []; public IReadOnlyList Playlists => _playlists; private Playlist? _currentPlaylist; public Playlist? CurrentPlaylist { get { return _currentPlaylist; } set { Playlist? oldPlaylist = _currentPlaylist; _currentPlaylist = value; CurrentPlaylistChanged?.Invoke(this, new(oldPlaylist, _currentPlaylist)); } } public event EventHandler? CurrentPlaylistChanged; public event EventHandler? PlaylistAdded; public event EventHandler? PlaylistRemoved; public event EventHandler? PlaylistSaveFailed; public PlaylistManager(IPlaylistRepository playlistRepository) { this.playlistRepository = playlistRepository; } public async Task InitializeAsync() { _playlists.AddRange(playlistRepository.Get()); foreach (Playlist playlist in _playlists) { playlist.PlaylistUpdated += OnPlaylistUpdated; foreach (PlaylistSong song in playlist.Songs) { _playlistsBySongUid[song.UID] = playlist; } } CurrentPlaylist = _playlists.Count > 0 ? _playlists[0] : await AddPlaylistAsync(); } public async Task AddPlaylistAsync() { Playlist playlist = new("New Playlist"); playlist.PlaylistUpdated += OnPlaylistUpdated; _playlists.Add(playlist); foreach (PlaylistSong song in playlist.Songs) { _playlistsBySongUid[song.UID] = playlist; } await SavePlaylistAsync(playlist); PlaylistAdded?.Invoke(this, new(playlist)); return playlist; } public void RemovePlaylist(Playlist playlist) { playlist.PlaylistUpdated -= OnPlaylistUpdated; _playlists.Remove(playlist); foreach (PlaylistSong song in playlist.Songs) { _playlistsBySongUid.Remove(song.UID); } playlistRepository.Delete(playlist); PlaylistRemoved?.Invoke(this, new(playlist)); } public Playlist? FindPlaylistContaining(PlaylistSong playlistSong) { return _playlistsBySongUid.GetValueOrDefault(playlistSong.UID); } public Playlist? FindPlaylistContaining(string playlistSongUID) { return _playlistsBySongUid.GetValueOrDefault(playlistSongUID); } private async void OnPlaylistUpdated(object? sender, PlaylistUpdatedEventArgs e) { if (sender is not Playlist playlist) return; switch (e.Action) { case PlaylistUpdateAction.Add: foreach (PlaylistSong song in e.Songs) { _playlistsBySongUid[song.UID] = playlist; } break; case PlaylistUpdateAction.Remove: foreach (PlaylistSong song in e.Songs) { _playlistsBySongUid.Remove(song.UID); } break; } await SavePlaylistAsync(playlist); } private async Task SavePlaylistAsync(Playlist playlist) { try { await playlistRepository.SaveAsync(playlist); } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { PlaylistSaveFailed?.Invoke(this, new(playlist, ex)); } } }