MyBookmark/Modules.Library.Domain/Entities/MediaContent/Items/Anime/AnimeTitle.cs
THE_KONDRAT 7b16d72329 ui and login
mongo => postgres
2024-11-03 16:08:39 +03:00

163 lines
6.4 KiB
C#

using Modules.Library.Domain.Entities.MediaContent.CommonProperties;
namespace Modules.Library.Domain.Entities.MediaContent.Items.Anime;
public class AnimeTitle : Entity
{
public CommonProperties.CommonProperties CommonProperties { get; protected set; } = default!;
private readonly List<AnimeItem> _items = [];
public IReadOnlyCollection<AnimeItem> Items => _items.ToList().AsReadOnly();
public bool Completed { get; private set; }
public TimeSpan ExpirationTime { get; private set; }
private AnimeTitle() { }
private AnimeTitle(Models.AnimeTitle title)
{
Id = title.Id;
Deleted = title.Deleted;
CommonProperties = MediaContent.CommonProperties.CommonProperties.New(title.CommonProperties);
Completed = title.Completed;
ExpirationTime = title.ExpirationTime;
foreach(var item in title.Items)
{
if (item is Models.AnimeEpisode episode)
{
_items.Add(AnimeEpisode.New(episode));
}
else if (item is Models.AnimeSeason season)
{
_items.Add(AnimeSeason.New(season));
}
}
}
public AnimeTitle(IEnumerable<NameItem> names)
{
CommonProperties = new CommonProperties.CommonProperties(names);
}
public static AnimeTitle New(Models.AnimeTitle title) => new(title);
public AnimeEpisode AddEpisode(AnimeEpisodeType episodeType, int? number = null) =>
CreateAndAddEpisode(episodeType, number:number);
public AnimeEpisode AddEpisodeAsVariant(AnimeEpisodeType episodeType, ushort order, int? number = null) =>
CreateAndAddEpisode(episodeType, order, number: number);
private AnimeEpisode CreateAndAddEpisode(AnimeEpisodeType type, ushort? order = null, ushort? variant = null, int? number = null)
{
StructureAction(() =>
{
(order, variant) = AnimeItem.GetOrderAndVariant(_items, order, variant);
number ??= _items.OfType<AnimeEpisode>().Select(q => q.Number).DefaultIfEmpty(-1).Max() + 1;
_items.Add(new AnimeEpisode(this, null, type, order.Value, variant.Value, number));
CheckIfCompleted();
});
return _items.OfType<AnimeEpisode>().OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First();
}
public AnimeEpisode AddEpisode(AnimeEpisodeType episodeType, IEnumerable<NameItem> names, int? number = null) =>
CreateAndAddEpisode(episodeType, names, number:number);
public AnimeEpisode AddEpisodeAsVariant(AnimeEpisodeType episodeType, IEnumerable<NameItem> names, ushort order, int? number = null) =>
CreateAndAddEpisode(episodeType, names, order, number:number);
private AnimeEpisode CreateAndAddEpisode(AnimeEpisodeType type, IEnumerable<NameItem> names,
ushort? order = null, ushort? variant = null, int? number = null)
{
StructureAction(() =>
{
(order, variant) = AnimeItem.GetOrderAndVariant(_items, order, variant);
number ??= _items.OfType<AnimeEpisode>().Select(q => q.Number).DefaultIfEmpty(-1).Max() + 1;
_items.Add(new AnimeEpisode(this, null, type, names, order.Value, variant.Value, number));
CheckIfCompleted();
});
return _items.OfType<AnimeEpisode>().OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First();
}
public void RemoveEpisode(ushort order, ushort variant)
{
var episode = _items.OfType<AnimeEpisode>().FirstOrDefault(q => q.Order == order && q.Variant == variant) ??
throw new Exception("EpisodeNotFoundException");
_items.Remove(episode);
}
public AnimeSeason AddSeason()
{
StructureAction(() =>
{
(ushort order, _) = AnimeItem.GetOrderAndVariant(_items);
var number = _items.OfType<AnimeSeason>().Select(q => q.Number).DefaultIfEmpty(-1).Max() + 1;
var season = new AnimeSeason(this, order, number);
_items.Add(season);
});
return _items.OfType<AnimeSeason>().OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First();
}
public AnimeSeason AddSeason(IEnumerable<NameItem> names, int? number = null)
{
StructureAction(() =>
{
(ushort order, _) = AnimeItem.GetOrderAndVariant(_items);
number ??= _items.OfType<AnimeSeason>().Select(q => q.Number).DefaultIfEmpty(-1).Max() + 1;
var season = new AnimeSeason(this, names, order, number);
_items.Add(season);
});
return _items.OfType<AnimeSeason>().OrderByDescending(q => q.Order).ThenByDescending(q => q.Variant).First();
}
/*
public void AddSeasonAsVariant(AnimeEpisodeType episodeType, ushort order)
{
if (order < 0 || order > _shadow.items.Select(q => q.order).DefaultIfEmpty<ushort>(0).Max())
throw new ArgumentOutOfRangeException(nameof(order));
var episode = new AnimeEpisodeShadow
{
type = episodeType,
order = order,
variant = AnimeItem.GetNewVariant(_shadow.items, order),
number = _shadow.items.OfType<AnimeEpisodeShadow>().FirstOrDefault(q => q.order == order)?.number,
};
_shadow.items.Add(episode);
CheckIsCompleted();
}
*/
//public void RemoveSeason(ushort order, ushort variant)
public void RemoveSeason(ushort order)
{
var season = _items.OfType<AnimeSeason>().FirstOrDefault(q => q.Order == order) ??
throw new Exception("SeasonNotFoundException");
_items.Remove(season);
}
public void SetCompleted() => Completed = true;
public void SetNotCompleted() => Completed = false;
public void SetExpirationTime(TimeSpan value) => StructureAction(() => ExpirationTime = value);
public void Delete() => Deleted = true;
internal void CheckIfCompleted()
{
var itemsQuery = Items.AsQueryable();
var ucompletedSeasons = itemsQuery
.Any(q => !q.CommonProperties.ReleaseDate.HasValue);
var lastEpisodeReleaseDate = itemsQuery
.OrderByDescending(q => q.CommonProperties.ReleaseDate)
.FirstOrDefault()?.CommonProperties.ReleaseDate;
if (ucompletedSeasons || lastEpisodeReleaseDate >= DateTime.UtcNow - ExpirationTime) SetNotCompleted();
else SetCompleted();
}
protected void StructureAction(Action action)
{
action();
CheckIfCompleted();
}
}