using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using NzbDrone.Common.Extensions; using NzbDrone.Core.Books; using NzbDrone.Core.MediaCover; using Readarr.Api.V1.Author; using Readarr.Http.REST; namespace Readarr.Api.V1.Books { public class BookResource : RestResource { public string Title { get; set; } public string AuthorTitle { get; set; } public string SeriesTitle { get; set; } public string Disambiguation { get; set; } public string Overview { get; set; } public int AuthorId { get; set; } public string ForeignBookId { get; set; } public string ForeignEditionId { get; set; } public string TitleSlug { get; set; } public bool Monitored { get; set; } public bool AnyEditionOk { get; set; } public Ratings Ratings { get; set; } public DateTime? ReleaseDate { get; set; } public int PageCount { get; set; } public List Genres { get; set; } public AuthorResource Author { get; set; } public List Images { get; set; } public List Links { get; set; } public BookStatisticsResource Statistics { get; set; } public DateTime? Added { get; set; } public AddBookOptions AddOptions { get; set; } public string RemoteCover { get; set; } public List Editions { get; set; } //Hiding this so people don't think its usable (only used to set the initial state) [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool Grabbed { get; set; } } public static class BookResourceMapper { public static BookResource ToResource(this Book model) { if (model == null) { return null; } var selectedEdition = model.Editions?.Value.Where(x => x.Monitored).SingleOrDefault(); var title = selectedEdition?.Title ?? model.Title; var authorTitle = $"{model.Author?.Value?.Metadata?.Value?.SortNameLastFirst} {title}"; var seriesLinks = model.SeriesLinks?.Value?.OrderBy(x => x.SeriesPosition); var seriesTitle = seriesLinks?.Select(x => x?.Series?.Value?.Title + (x?.Position.IsNotNullOrWhiteSpace() ?? false ? $" #{x.Position}" : string.Empty)).ConcatToString("; "); return new BookResource { Id = model.Id, AuthorId = model.AuthorId, ForeignBookId = model.ForeignBookId, ForeignEditionId = model.Editions?.Value?.SingleOrDefault(x => x.Monitored)?.ForeignEditionId, TitleSlug = model.TitleSlug, Monitored = model.Monitored, AnyEditionOk = model.AnyEditionOk, ReleaseDate = model.ReleaseDate, PageCount = selectedEdition?.PageCount ?? 0, Genres = model.Genres, Title = title, AuthorTitle = authorTitle, SeriesTitle = seriesTitle, Disambiguation = selectedEdition?.Disambiguation, Images = selectedEdition?.Images ?? new List(), Links = model.Links.Concat(selectedEdition?.Links ?? new List()).ToList(), Ratings = selectedEdition?.Ratings ?? new Ratings(), Added = model.Added, }; } public static Book ToModel(this BookResource resource) { if (resource == null) { return null; } var author = resource.Author?.ToModel() ?? new NzbDrone.Core.Books.Author(); return new Book { Id = resource.Id, ForeignBookId = resource.ForeignBookId, ForeignEditionId = resource.ForeignEditionId, TitleSlug = resource.TitleSlug, Title = resource.Title, Monitored = resource.Monitored, AnyEditionOk = resource.AnyEditionOk, Editions = resource.Editions.ToModel(), AddOptions = resource.AddOptions, Author = author, AuthorMetadata = author.Metadata.Value }; } public static Book ToModel(this BookResource resource, Book book) { var updatedBook = resource.ToModel(); book.ApplyChanges(updatedBook); book.Editions = updatedBook.Editions; return book; } public static List ToResource(this IEnumerable models) { return models?.Select(ToResource).ToList(); } public static List ToModel(this IEnumerable resources) { return resources.Select(ToModel).ToList(); } } }