using System; using System.Collections.Generic; using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Library { /// /// Single definition of "which alternate version was most recently played" shared by the resume tile /// (), the media-source default ordering and Next Up. /// Each call site declares its own eligibility rule so the intentional differences (resumable-only vs. /// resumable-or-completed) are visible in one place instead of being re-implemented divergently. /// The SQL resume query keeps its own translation of the same rule. /// public static class VersionPlaybackSelector { /// /// Selects the entry whose user data has the greatest , /// considering only entries that satisfy . On an exact tie the first /// encountered entry wins. /// /// The candidate type (e.g. a version item or a media source). /// The candidates to choose from. /// Resolves the user data for a candidate, or null when it has none. /// Whether a candidate's user data makes it a valid winner. /// The most recently played eligible candidate, or default when none qualify. public static T? SelectMostRecentlyPlayed( IEnumerable items, Func dataSelector, Func isEligible) { ArgumentNullException.ThrowIfNull(items); ArgumentNullException.ThrowIfNull(dataSelector); ArgumentNullException.ThrowIfNull(isEligible); T? winner = default; var winnerDate = DateTime.MinValue; var hasWinner = false; foreach (var item in items) { var data = dataSelector(item); if (data is null || !isEligible(data)) { continue; } var date = data.LastPlayedDate ?? DateTime.MinValue; if (!hasWinner || date > winnerDate) { winner = item; winnerDate = date; hasWinner = true; } } return winner; } } }