152 lines
5.1 KiB
C#

using ApplicationServices;
using AudibleApi;
using AudibleApi.Common;
using AudibleUtilities;
using DataLayer;
using Dinah.Core;
using Dinah.Core.Threading;
using FileLiberator;
using LibationFileManager;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace LibationUiBase.SeriesView
{
public class SeriesItem : SynchronizeInvoker, INotifyPropertyChanged
{
public object Cover { get; private set; }
public SeriesOrder Order { get; }
public string Title => Item.TitleWithSubtitle;
public SeriesButton Button { get; }
public Item Item { get; }
public event PropertyChangedEventHandler PropertyChanged;
private SeriesItem(Item item, string order, bool inLibrary, bool inWishList)
{
Item = item;
Order = new SeriesOrder(order);
Button = Item.Plans.Any(p => p.IsAyce) ? new AyceButton(item, inLibrary) : new WishlistButton(item, inLibrary, inWishList);
LoadCover(item.PictureId);
Button.PropertyChanged += DownloadButton_PropertyChanged;
}
public void ViewOnAudible(string localeString)
{
var locale = Localization.Get(localeString);
var link = $"https://www.audible.{locale.TopDomain}/pd/{Item.ProductId}";
Go.To.Url(link);
}
private void DownloadButton_PropertyChanged(object sender, PropertyChangedEventArgs e)
=> OnPropertyChanged(nameof(Button));
private void OnPropertyChanged(string propertyName)
=> Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
private void LoadCover(string pictureId)
{
var (isDefault, picture) = PictureStorage.GetPicture(new PictureDefinition(pictureId, PictureSize._80x80));
if (isDefault)
{
PictureStorage.PictureCached += PictureStorage_PictureCached;
}
Cover = BaseUtil.LoadImage(picture, PictureSize._80x80);
}
private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e)
{
if (e?.Definition.PictureId != null && Item?.PictureId != null)
{
byte[] picture = e.Picture;
if ((picture == null || picture.Length != 0) && e.Definition.PictureId == Item.PictureId)
{
Cover = BaseUtil.LoadImage(e.Picture, PictureSize._80x80);
PictureStorage.PictureCached -= PictureStorage_PictureCached;
OnPropertyChanged(nameof(Cover));
}
}
}
public static async Task<Dictionary<Item, List<SeriesItem>>> GetAllSeriesItemsAsync(LibraryBook libraryBook)
{
var api = await libraryBook.GetApiAsync();
//Get Item for each series that this book belong to
var seriesItemsTask = api.GetCatalogProductsAsync(libraryBook.Book.SeriesLink.Select(s => s.Series.AudibleSeriesId), CatalogOptions.ResponseGroupOptions.Media | CatalogOptions.ResponseGroupOptions.Relationships);
using var semaphore = new SemaphoreSlim(10);
//Start getting the wishlist in the background
var wishlistTask = api.GetWishListProductsAsync(
new WishListOptions
{
PageNumber = 0,
NumberOfResultPerPage = 50,
ResponseGroups = WishListOptions.ResponseGroupOptions.None
},
numItemsPerRequest: 50,
semaphore);
var items = new Dictionary<Item, List<Item>>();
//Get all children of all series
foreach (var series in await seriesItemsTask)
{
//Books that are part of series have RelationshipType.Series
//Podcast episodes have RelationshipType.Episode
var childrenAsins = series.Relationships
.Where(r => r.RelationshipType is RelationshipType.Series or RelationshipType.Episode && r.RelationshipToProduct is RelationshipToProduct.Child)
.Select(r => r.Asin)
.ToList();
if (childrenAsins.Count > 0)
{
var children = await api.GetCatalogProductsAsync(childrenAsins, CatalogOptions.ResponseGroupOptions.ALL_OPTIONS, 50, semaphore);
//If the price is null, this item is not available to the user
var childrenWithPrices = children.Where(p => p.Price != null).ToList();
if (childrenWithPrices.Count > 0)
items[series] = childrenWithPrices;
}
}
//Await the wishlist asins
var wishlistAsins = (await wishlistTask).Select(w => w.Asin).ToHashSet();
var fullLib = DbContexts.GetLibrary_Flat_NoTracking();
var seriesEntries = new Dictionary<Item, List<SeriesItem>>();
//Create a SeriesItem liste for each series.
foreach (var series in items.Keys)
{
ApiExtended.SetSeries(series, items[series]);
seriesEntries[series] = new List<SeriesItem>();
foreach (var item in items[series].Where(i => !string.IsNullOrEmpty(i.PictureId)))
{
var order = item.Series.Single(s => s.Asin == series.Asin).Sequence;
//Match the account/book in the database
var inLibrary = fullLib.Any(lb => lb.Account == libraryBook.Account && lb.Book.AudibleProductId == item.ProductId && !lb.AbsentFromLastScan);
var inWishList = wishlistAsins.Contains(item.Asin);
seriesEntries[series].Add(new SeriesItem(item, order, inLibrary, inWishList));
}
}
return seriesEntries;
}
~SeriesItem()
{
PictureStorage.PictureCached -= PictureStorage_PictureCached;
Button.PropertyChanged -= DownloadButton_PropertyChanged;
}
}
}