import '../../core/contracts/tmdb.dart'; import 'tmdb_image_url.dart'; class TmdbImageSelector { static TmdbImage? bestImage( List images, { bool preferNeutral = false, }) { if (images.isEmpty) return null; if (preferNeutral) { final neutrals = images .where((i) => i.filePath.isNotEmpty && i.isLanguageNeutral) .toList(); if (neutrals.isNotEmpty) return _pickBest(neutrals); } return _pickBest(images); } static TmdbImage? _pickBest(List images) { TmdbImage? best; for (final image in images) { if (image.filePath.isEmpty) continue; if (best == null || _isBetter(image, best)) best = image; } return best; } static String? backdropUrl( TmdbImageSet? imageSet, String? imageBaseUrl, { String size = 'original', }) { if (imageBaseUrl == null || imageBaseUrl.isEmpty) return null; final image = bestImage( imageSet?.backdrops ?? const [], preferNeutral: true, ); return TmdbImageUrl.backdrop(imageBaseUrl, image?.filePath, size: size); } static String? posterUrl( TmdbImageSet? imageSet, String? imageBaseUrl, { String size = 'w500', }) { if (imageBaseUrl == null || imageBaseUrl.isEmpty) return null; final image = bestImage(imageSet?.posters ?? const []); return TmdbImageUrl.poster(imageBaseUrl, image?.filePath, size: size); } static String? logoUrl( TmdbImageSet? imageSet, String? imageBaseUrl, { String? language, String size = 'w500', }) { if (imageBaseUrl == null || imageBaseUrl.isEmpty) return null; final logos = imageSet?.logos ?? const []; if (logos.isEmpty) return null; final lang = _iso639Of(language); final image = (lang != null ? _pickBest(_withLang(logos, lang)) : null) ?? _pickBest(_withLang(logos, 'en')) ?? _pickBest(logos.where((i) => i.isLanguageNeutral).toList()) ?? _pickBest(logos); return TmdbImageUrl.logo(imageBaseUrl, image?.filePath, size: size); } static List _withLang(List images, String iso) => images.where((i) => i.iso639 == iso).toList(); static String? _iso639Of(String? language) { if (language == null || language.isEmpty) return null; final dash = language.indexOf('-'); final code = dash >= 0 ? language.substring(0, dash) : language; return code.isEmpty ? null : code.toLowerCase(); } static List buildFallbackUrls({ required String? primaryUrl, required Iterable candidates, }) { final urls = []; for (final url in candidates) { if (url == null || url.isEmpty || url == primaryUrl) continue; if (!urls.contains(url)) urls.add(url); } return urls; } static bool _isBetter(TmdbImage candidate, TmdbImage current) { final voteCompare = (candidate.voteAverage ?? 0).compareTo( current.voteAverage ?? 0, ); if (voteCompare != 0) return voteCompare > 0; final pixelsCompare = (candidate.width * candidate.height).compareTo( current.width * current.height, ); if (pixelsCompare != 0) return pixelsCompare > 0; return candidate.filePath.compareTo(current.filePath) < 0; } }