using System; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Users; using MoreLinq; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.Threading.Tasks; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Controller.Entities.TV { /// /// Class Season /// public class Season : Folder, IHasSeries, IHasLookupInfo { [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } } [IgnoreDataMember] public override bool IsPreSorted { get { return true; } } [IgnoreDataMember] public override bool SupportsDateLastMediaAdded { get { return true; } } [IgnoreDataMember] public override Guid? DisplayParentId { get { var series = Series; return series == null ? ParentId : series.Id; } } [IgnoreDataMember] public string SeriesSortName { get; set; } public string FindSeriesSortName() { var series = Series; return series == null ? SeriesSortName : series.SortName; } // Genre, Rating and Stuido will all be the same protected override IEnumerable GetIndexByOptions() { return new List { {"None"}, {"Performer"}, {"Director"}, {"Year"}, }; } public override List GetUserDataKeys() { var list = base.GetUserDataKeys(); var series = Series; if (series != null) { list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000"))); } return list; } public override int GetChildCount(User user) { return GetChildren(user, true).Count(); } /// /// This Episode's Series Instance /// /// The series. [IgnoreDataMember] public Series Series { get { return FindParent(); } } [IgnoreDataMember] public string SeriesPath { get { var series = Series; if (series != null) { return series.Path; } return System.IO.Path.GetDirectoryName(Path); } } [IgnoreDataMember] public override string PresentationUniqueKey { get { if (IndexNumber.HasValue) { var series = Series; if (series != null) { return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000"); } } return base.PresentationUniqueKey; } } /// /// Creates the name of the sort. /// /// System.String. protected override string CreateSortName() { return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } [IgnoreDataMember] public bool IsMissingSeason { get { return (IsVirtualItem) && !IsUnaired; } } [IgnoreDataMember] public bool IsVirtualUnaired { get { return (IsVirtualItem) && IsUnaired; } } [IgnoreDataMember] public bool IsSpecialSeason { get { return (IndexNumber ?? -1) == 0; } } protected override Task> GetItemsInternal(InternalItemsQuery query) { if (query.User == null) { return base.GetItemsInternal(query); } var user = query.User; Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); var items = GetEpisodes(user).Where(filter); var result = PostFilterAndSort(items, query); return Task.FromResult(result); } /// /// Gets the episodes. /// /// The user. /// IEnumerable{Episode}. public IEnumerable GetEpisodes(User user) { var config = user.Configuration; return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } public IEnumerable GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null); } public IEnumerable GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable allSeriesEpisodes) { return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes); } public IEnumerable GetEpisodes() { var episodes = GetRecursiveChildren().OfType(); var series = Series; if (series != null && series.ContainsEpisodesWithoutSeasonFolders) { var seasonNumber = IndexNumber; var list = episodes.ToList(); if (seasonNumber.HasValue) { list.AddRange(series.GetRecursiveChildren().OfType() .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value)); } else { list.AddRange(series.GetRecursiveChildren().OfType() .Where(i => !i.ParentIndexNumber.HasValue)); } episodes = list.DistinctBy(i => i.Id); } return episodes; } public override IEnumerable GetChildren(User user, bool includeLinkedChildren) { return GetEpisodes(user); } protected override bool GetBlockUnratedValue(UserPolicy config) { // Don't block. Let either the entire series rating or episode rating determine it return false; } public override UnratedItem GetBlockUnratedType() { return UnratedItem.Series; } [IgnoreDataMember] public string SeriesName { get; set; } [IgnoreDataMember] public Guid? SeriesId { get; set; } public string FindSeriesName() { var series = Series; return series == null ? SeriesName : series.Name; } public Guid? FindSeriesId() { var series = Series; return series == null ? (Guid?)null : series.Id; } /// /// Gets the lookup information. /// /// SeasonInfo. public SeasonInfo GetLookupInfo() { var id = GetItemLookupInfo(); var series = Series; if (series != null) { id.SeriesProviderIds = series.ProviderIds; id.AnimeSeriesIndex = series.AnimeSeriesIndex; } return id; } /// /// This is called before any metadata refresh and returns true or false indicating if changes were made /// /// true if XXXX, false otherwise. public override bool BeforeMetadataRefresh() { var hasChanges = base.BeforeMetadataRefresh(); if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path)) { IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path); // If a change was made record it if (IndexNumber.HasValue) { hasChanges = true; } } return hasChanges; } } }