using ApplicationServices;
using DataLayer;
using Dinah.Core;
using FileLiberator;
using LibationFileManager;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace LibationUiBase.GridView
{
public enum RemoveStatus
{
NotRemoved,
Removed,
SomeRemoved
}
/// The View Model base for the DataGridView
public abstract class GridEntry : ReactiveObject
{
[Browsable(false)] public string AudibleProductId => Book.AudibleProductId;
[Browsable(false)] public LibraryBook LibraryBook { get; protected set; }
[Browsable(false)] public float SeriesIndex { get; protected set; }
[Browsable(false)] public abstract DateTime DateAdded { get; }
[Browsable(false)] public Book Book => LibraryBook.Book;
#region Model properties exposed to the view
protected bool? remove = false;
private EntryStatus _liberate;
private string _purchasedate;
private string _length;
private LastDownloadStatus _lastDownload;
private Lazy
", "\r\n\r\n") ?? "");
return doc.DocumentNode.InnerText.Trim();
}
private static string TrimTextToWord(string text, int maxLength)
{
return
text.Length <= maxLength ?
text :
text.Substring(0, maxLength - 3) + "...";
}
///
/// This information should not change during lifetime, so call only once.
/// Maximum of 5 text rows will fit in 80-pixel row height.
///
private static string GetMiscDisplay(LibraryBook libraryBook)
{
var details = new List();
var locale = libraryBook.Book.Locale.DefaultIfNullOrWhiteSpace("[unknown]");
var acct = libraryBook.Account.DefaultIfNullOrWhiteSpace("[unknown]");
details.Add($"Account: {locale} - {acct}");
if (libraryBook.Book.HasPdf())
details.Add("Has PDF");
if (libraryBook.Book.IsAbridged)
details.Add("Abridged");
if (libraryBook.Book.DatePublished.HasValue)
details.Add($"Date pub'd: {libraryBook.Book.DatePublished.Value:MM/dd/yyyy}");
// this goes last since it's most likely to have a line-break
if (!string.IsNullOrWhiteSpace(libraryBook.Book.Publisher))
details.Add($"Pub: {libraryBook.Book.Publisher.Trim()}");
if (!details.Any())
return "[details not imported]";
return string.Join("\r\n", details);
}
#endregion
///
/// Creates for all non-episode books in an enumeration of .
///
/// Can be called from any thread, but requires the calling thread's to be valid.
public static async Task> GetAllProductsAsync(IEnumerable libraryBooks, Func includeIf, Func factory)
where TEntry : GridEntry
{
var products = libraryBooks.Where(includeIf).ToArray();
if (products.Length == 0)
return [];
int parallelism = int.Max(1, Environment.ProcessorCount - 1);
(int batchSize, int rem) = int.DivRem(products.Length, parallelism);
if (rem != 0) batchSize++;
var syncContext = SynchronizationContext.Current;
//Asynchronously create a GridEntry for every book in the library
var tasks = products.Chunk(batchSize).Select(batch => Task.Run(() =>
{
SynchronizationContext.SetSynchronizationContext(syncContext);
return batch.Select(factory).OfType().ToArray();
}));
return (await Task.WhenAll(tasks)).SelectMany(a => a).ToList();
}
~GridEntry()
{
PictureStorage.PictureCached -= PictureStorage_PictureCached;
UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged;
}
}
}