using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; namespace MediaBrowser.Controller.Entities.TV { /// /// Class Season /// public class Season : Folder, IHasSeries, IHasLookupInfo { /// /// Seasons are just containers /// /// true if [include in index]; otherwise, false. [IgnoreDataMember] public override bool IncludeInIndex { get { return false; } } [IgnoreDataMember] public override bool IsPreSorted { get { return true; } } /// /// We want to group into our Series /// /// true if [group in index]; otherwise, false. [IgnoreDataMember] public override bool GroupInIndex { get { return true; } } /// /// Override this to return the folder that should be used to construct a container /// for this item in an index. GroupInIndex should be true as well. /// /// The index container. [IgnoreDataMember] public override Folder IndexContainer { get { return Series; } } // Genre, Rating and Stuido will all be the same protected override IEnumerable GetIndexByOptions() { return new List { {LocalizedStrings.Instance.GetString("NoneDispPref")}, {LocalizedStrings.Instance.GetString("PerformerDispPref")}, {LocalizedStrings.Instance.GetString("DirectorDispPref")}, {LocalizedStrings.Instance.GetString("YearDispPref")}, }; } /// /// Gets the user data key. /// /// System.String. public override string GetUserDataKey() { if (Series != null) { var seasonNo = IndexNumber ?? 0; return Series.GetUserDataKey() + seasonNo.ToString("000"); } return base.GetUserDataKey(); } /// /// The _series /// private Series _series; /// /// This Episode's Series Instance /// /// The series. [IgnoreDataMember] public Series Series { get { return _series ?? (_series = FindParent()); } } [IgnoreDataMember] public string SeriesPath { get { var series = Series; if (series != null) { return series.Path; } return System.IO.Path.GetDirectoryName(Path); } } /// /// Our rating comes from our series /// [IgnoreDataMember] public override string OfficialRatingForComparison { get { var series = Series; return series != null ? series.OfficialRatingForComparison : base.OfficialRatingForComparison; } } /// /// Creates the name of the sort. /// /// System.String. protected override string CreateSortName() { return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } private IEnumerable GetEpisodes() { var series = Series; if (series != null && series.ContainsEpisodesWithoutSeasonFolders) { var seasonNumber = IndexNumber; if (seasonNumber.HasValue) { return series.RecursiveChildren.OfType() .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value); } } return Children.OfType(); } [IgnoreDataMember] public bool IsMissingSeason { get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } } [IgnoreDataMember] public bool IsUnaired { get { return GetEpisodes().All(i => i.IsUnaired); } } [IgnoreDataMember] public bool IsVirtualUnaired { get { return LocationType == LocationType.Virtual && IsUnaired; } } [IgnoreDataMember] public bool IsMissingOrVirtualUnaired { get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } } [IgnoreDataMember] public bool IsSpecialSeason { get { return (IndexNumber ?? -1) == 0; } } /// /// Gets the episodes. /// /// The user. /// IEnumerable{Episode}. public IEnumerable GetEpisodes(User user) { var config = user.Configuration; return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } public IEnumerable GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { var episodes = GetRecursiveChildren(user) .OfType(); if (IndexNumber.HasValue) { var series = Series; if (series != null) { return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes); } } if (!includeMissingEpisodes) { episodes = episodes.Where(i => !i.IsMissingEpisode); } if (!includeVirtualUnairedEpisodes) { episodes = episodes.Where(i => !i.IsVirtualUnaired); } return LibraryManager .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) .Cast(); } public override IEnumerable GetChildren(User user, bool includeLinkedChildren) { return GetEpisodes(user); } protected override bool GetBlockUnratedValue(UserConfiguration config) { // Don't block. Let either the entire series rating or episode rating determine it return false; } [IgnoreDataMember] public string SeriesName { get { var series = Series; return series == null ? null : series.Name; } } /// /// 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(); var locationType = LocationType; if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) { if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path)) { IndexNumber = IndexNumber ?? TVUtils.GetSeasonNumberFromPath(Path); // If a change was made record it if (IndexNumber.HasValue) { hasChanges = true; } } } return hasChanges; } } }