using DataLayer; using Dinah.Core.Collections.Generic; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace LibationUiBase.GridView { /// The View Model for a LibraryBook that is ContentType.Parent public class SeriesEntry : GridEntry { public List Children { get; } public override DateTime DateAdded => Children.Max(c => c.DateAdded); private bool suspendCounting = false; public void ChildRemoveUpdate() { if (suspendCounting) return; var removeCount = Children.Count(c => c.Remove == true); remove = removeCount == 0 ? false : removeCount == Children.Count ? true : null; RaisePropertyChanged(nameof(Remove)); } public override bool? Remove { get => remove; set { remove = value ?? false; suspendCounting = true; foreach (var item in Children) item.Remove = value; suspendCounting = false; RaisePropertyChanged(nameof(Remove)); } } public SeriesEntry(LibraryBook parent, LibraryBook child) : this(parent, new[] { child }) { } public SeriesEntry(LibraryBook parent, IEnumerable children) { LastDownload = new(); SeriesIndex = -1; Children = children .Select(c => new LibraryBookEntry(c, this)) .OrderByDescending(c => c.SeriesOrder) .ToList(); UpdateLibraryBook(parent); LoadCover(); } /// /// Creates for all episodic series in an enumeration of . /// /// Can be called from any thread, but requires the calling thread's to be valid. public static async Task> GetAllSeriesEntriesAsync(IEnumerable libraryBooks) { var seriesEntries = await GetAllProductsAsync(libraryBooks, lb => lb.Book.IsEpisodeParent(), lb => new SeriesEntry(lb, [])); var seriesDict = seriesEntries.ToDictionarySafe(s => s.AudibleProductId); await GetAllProductsAsync(libraryBooks, lb => lb.Book.IsEpisodeChild(), CreateAndLinkEpisodeEntry); //sort episodes by series order descending and update SeriesEntry foreach (var series in seriesEntries) { series.Children.Sort((a, b) => -a.SeriesOrder.CompareTo(b.SeriesOrder)); series.UpdateLibraryBook(series.LibraryBook); } return seriesEntries.Where(s => s.Children.Count != 0).ToList(); //Create a LibraryBookEntry for an episode and link it to its series parent LibraryBookEntry CreateAndLinkEpisodeEntry(LibraryBook episode) { foreach (var s in episode.Book.SeriesLink) { if (seriesDict.TryGetValue(s.Series.AudibleSeriesId, out var seriesParent)) { var entry = new LibraryBookEntry(episode, seriesParent); seriesParent.Children.Add(entry); return entry; } } return null; } } public void RemoveChild(LibraryBookEntry lbe) { Children.Remove(lbe); PurchaseDate = GetPurchaseDateString(); Length = GetBookLengthString(); } protected override string GetBookTags() => null; protected override int GetLengthInMinutes() => Children.Count == 0 ? 0 : Children.Sum(c => c.LibraryBook.Book.LengthInMinutes); protected override DateTime GetPurchaseDate() => Children.Count == 0 ? default : Children.Min(c => c.LibraryBook.DateAdded); } }