using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using ErsatzTV.Core.Domain; using LanguageExt; using static LanguageExt.Prelude; namespace ErsatzTV.Application.Movies { internal static class Mapper { internal static MovieViewModel ProjectToViewModel(Movie movie, Option maybeJellyfin) { MovieMetadata metadata = Optional(movie.MovieMetadata).Flatten().Head(); return new MovieViewModel( metadata.Title, metadata.Year?.ToString(), metadata.Plot, metadata.Genres.Map(g => g.Name).ToList(), metadata.Tags.Map(t => t.Name).ToList(), metadata.Studios.Map(s => s.Name).ToList(), LanguagesForMovie(movie), metadata.Actors.OrderBy(a => a.Order).ThenBy(a => a.Id) .Map(a => MediaCards.Mapper.ProjectToViewModel(a, maybeJellyfin)) .ToList()) { Poster = Artwork(metadata, ArtworkKind.Poster, maybeJellyfin), FanArt = Artwork(metadata, ArtworkKind.FanArt, maybeJellyfin) }; } private static List LanguagesForMovie(Movie movie) { CultureInfo[] allCultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures); return movie.MediaVersions .Map(mv => mv.Streams.Filter(s => s.MediaStreamKind == MediaStreamKind.Audio).Map(s => s.Language)) .Flatten() .Distinct() .Map( lang => allCultures.Filter( ci => string.Equals(ci.ThreeLetterISOLanguageName, lang, StringComparison.OrdinalIgnoreCase))) .Sequence() .Flatten() .ToList(); } private static string Artwork( Metadata metadata, ArtworkKind artworkKind, Option maybeJellyfin) { string artwork = Optional(metadata.Artwork.FirstOrDefault(a => a.ArtworkKind == artworkKind)) .Match(a => a.Path, string.Empty); if (maybeJellyfin.IsSome && artwork.StartsWith("jellyfin://")) { string address = maybeJellyfin.Map(ms => ms.Connections.HeadOrNone().Map(c => c.Address)) .Flatten() .IfNone("jellyfin://"); artwork = artwork.Replace("jellyfin://", address); if (artworkKind is ArtworkKind.Poster or ArtworkKind.Thumbnail) { artwork += "&fillHeight=440"; } } return artwork; } } }