using Modules.Library.Domain.Entities.MediaContent.CommonProperties; namespace Modules.Library.Domain.Entities.MediaContent.Items.Anime; public sealed class AnimeSeason : AnimeItem, IVariantItem { private List _episodes = []; public IReadOnlyCollection Episodes => _episodes.AsReadOnly(); public int? Number { get; private set; } public string? Director { get; private set; } public string? OriginCountry { get; private set; } private AnimeSeason() : base() { } private AnimeSeason(Models.AnimeSeason season) : base() { Id = season.Id; CommonProperties = MediaContent.CommonProperties.CommonProperties.New(season.CommonProperties); Deleted = season.Deleted; Number = season.Number; Order = season.Order; //Variant = season.Variant; Director = season.Director; OriginCountry = season.OriginCountry; Completed = season.Completed; ExpirationTime = season.ExpirationTime; _episodes = season.Episodes.Select(AnimeEpisode.New).ToList(); } internal AnimeSeason(AnimeTitle title, ushort order, int? number = null) : base(title) { Order = order; Number = number; } internal AnimeSeason(AnimeTitle title, IEnumerable names, ushort order, int? number = null) : base(title, names) { Order = order; Number = number; } internal static AnimeSeason New(Models.AnimeSeason season) => new(season); public AnimeEpisode AddEpisode(AnimeEpisodeType type, int? number = null) => CreateAndAddEpisode(type, number: number); public AnimeEpisode AddEpisodeAsVariant(AnimeEpisodeType type, ushort order, int? number = null) => CreateAndAddEpisode(type, order, number:number); private AnimeEpisode CreateAndAddEpisode(AnimeEpisodeType type, ushort? order = null, ushort? variant = null, int? number = null) { StructureAction(() => { (order, variant) = GetOrderAndVariant(_episodes.Select(q => (AnimeItem)q), order, variant); _episodes.Add(new AnimeEpisode(_title, this, type, order.Value, variant.Value, number)); }); return _episodes.OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First(); } public AnimeEpisode AddEpisode(AnimeEpisodeType type, IEnumerable names, int? number = null) => CreateAndAddEpisode(type, names, number: number); public AnimeEpisode AddEpisodeAsVariant(AnimeEpisodeType type, IEnumerable names, ushort order, int? number = null) => CreateAndAddEpisode(type, names, order, number:number); private AnimeEpisode CreateAndAddEpisode(AnimeEpisodeType type, IEnumerable names, ushort? order = null, ushort? variant = null, int? number = null) { StructureAction(() => { (order, variant) = GetOrderAndVariant(_episodes.Select(q => (AnimeItem)q), order, variant); _episodes.Add(new AnimeEpisode(_title, this, type, names, order.Value, variant.Value, number)); }); return _episodes.OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First(); } public void RemoveEpisode(ushort order, ushort variant) { var episode = _episodes.FirstOrDefault(q => q.Order == order && q.Variant == variant) ?? throw new Exception("EpisodeNotFoundException"); _episodes.Remove(episode); } //public override void SetOrder(ushort order) => _title.SetItemOrder(Order, order); public override void SetOrder(ushort order) => SetItemOrder(_title.Items, Order, order); public override void SetVariant(ushort variant) => throw new NotImplementedException(); internal void AfterEpisodeExpirationTimeSet() => StructureAction(() => { }); public void SetNumber(int? number) => Number = number; public void SetDirector(string? director) => Director = director; public void SetOriginCountry(string? originCountry) => OriginCountry = originCountry; protected override void StructureAction(Action action) { action(); CheckIfCompleted(); _title.CheckIfCompleted(); //return new AnimeEpisode(title, this, episodeShadow); } internal void CheckIfCompleted() { var itemsQuery = Episodes.Where(q => !q.Deleted).AsQueryable(); var unreleasedEpisodesAreExists = itemsQuery .Any(q => !q.CommonProperties.ReleaseDate.HasValue); var lastEpisodeReleaseDate = itemsQuery .OrderByDescending(q => q.CommonProperties.ReleaseDate) .FirstOrDefault()?.CommonProperties.ReleaseDate; //return unreleasedEpisodesAreExists || lastEpisodeReleaseDate - DateTime.UtcNow > expirePeriod; if (unreleasedEpisodesAreExists || lastEpisodeReleaseDate >= DateTime.UtcNow - ExpirationTime) SetNotCompleted(); else SetCompleted(); } }