using Harmonia.Core.Extensions; using Harmonia.Core.Models; namespace Harmonia.Core.Playlists; public class Playlist { public string UID { get; init; } = Guid.NewGuid().ToString(); public string? Name { get; set; } public List Songs { get; init; } = []; // TODO: Change to "private init" once deserialization is fixed public List GroupOptions { get; set; } = []; public List SortOptions { get; set; } = []; public bool IsLocked { get; set; } public event EventHandler? PlaylistUpdated; public void AddSong(Song song, int? index = null) { AddSongs([song], index); } public void AddSongs(Song[] songs, int? index = null) { PlaylistSong[] playlistSongs = [.. songs.Select(song => new PlaylistSong(song))]; AddSongs(playlistSongs, index); } private void AddSongs(PlaylistSong[] playlistSongs, int? index = null) { if (IsLocked) return; int insertIndex = index ?? Songs.Count; Songs.InsertRange(insertIndex, playlistSongs); PlaylistUpdatedEventArgs eventArgs = new() { Action = PlaylistUpdateAction.Add, Index = insertIndex, Count = playlistSongs.Length, Songs = playlistSongs }; PlaylistUpdated?.Invoke(this, eventArgs); } public void MoveSong(PlaylistSong playlistSong, int newIndex) { int currentIndex = Songs.IndexOf(playlistSong); MoveSong(currentIndex, newIndex); } public void MoveSong(int oldIndex, int newIndex) { if (IsLocked) return; if (oldIndex == newIndex) return; PlaylistSong playlistSong = Songs[oldIndex]; Songs.Remove(playlistSong); Songs.Insert(newIndex, playlistSong); PlaylistUpdatedEventArgs eventArgs = new() { Action = PlaylistUpdateAction.Move, Index = oldIndex, Count = 1, Songs = [playlistSong], NewIndex = newIndex }; PlaylistUpdated?.Invoke(this, eventArgs); } public void SortSongs(PlaylistSong[] playlistSongs, SortOption[] sortOptions) { Dictionary oldPlaylistSongs = playlistSongs .OrderBy(Songs.IndexOf) .ToDictionary(Songs.IndexOf, playlistSong => playlistSong); Song[] songs = [.. playlistSongs.Select(playlistSong => playlistSong.Song)]; Song[] sortedSongs = [.. songs.SortBy(sortOptions)]; int currentSortIndex = 0; foreach (int index in oldPlaylistSongs.Keys) { PlaylistSong playlistSong = oldPlaylistSongs[index]; Song sortedSong = sortedSongs[currentSortIndex++]; PlaylistSong newPlaylistSong = playlistSongs.First(ps => ps.Song == sortedSong); if (newPlaylistSong == playlistSong) continue; Songs.RemoveAt(index); Songs.Insert(index, newPlaylistSong); } PlaylistUpdatedEventArgs eventArgs = new() { Action = PlaylistUpdateAction.Reset, Index = -1, Count = playlistSongs.Length, Songs = playlistSongs }; PlaylistUpdated?.Invoke(this, eventArgs); } public void RemoveSong(int index) { RemoveSongs(index, 1); } public void RemoveSongs(int index, int count) { PlaylistSong[] playlistSongs = [.. Songs.GetRange(index, count)]; RemoveSongs(playlistSongs); } public void RemoveSong(PlaylistSong playlistSong) { RemoveSongs([playlistSong]); } public void RemoveSongs(PlaylistSong[] playlistSongs) { if (IsLocked) return; List removedSongs = []; foreach (PlaylistSong playlistSong in playlistSongs) { if (Songs.Remove(playlistSong)) { removedSongs.Add(playlistSong); } } if (removedSongs.Count == 0) return; PlaylistUpdatedEventArgs eventArgs = new() { Action = PlaylistUpdateAction.Remove, Index = -1, Count = removedSongs.Count, Songs = playlistSongs }; PlaylistUpdated?.Invoke(this, eventArgs); } }