namespace Modules.Library.Domain.Entities.MediaContent.Items.Anime; public abstract class AnimeItem : Entity, IOrderableItem { protected readonly AnimeTitle _title = default!; public CommonProperties.CommonProperties CommonProperties { get; protected set; } = default!; public ushort Order { get; protected set; } public ushort Variant { get; protected set; } public bool Completed { get; protected set; } public override bool Deleted { get; protected set; } public TimeSpan ExpirationTime { get; protected set; } internal static Action SetOrderAction => (item, value) => item.Order = value; internal static Action SetVariantAction => (item, value) => item.Variant = value; private protected AnimeItem() { } internal AnimeItem(AnimeTitle title) { _title = title; CommonProperties = new CommonProperties.CommonProperties(); } internal AnimeItem(AnimeTitle title, Guid nameOriginalLanguageId, string nameOriginal) { _title = title; CommonProperties = new CommonProperties.CommonProperties(nameOriginalLanguageId, nameOriginal); } public abstract void SetOrder(ushort order); public abstract void SetVariant(ushort variant); private static ushort GetNewOrder(IEnumerable items) => (ushort)(items.Select(q => (int)q.Order).DefaultIfEmpty(-1).Max() + 1); private static ushort GetNewVariant(IEnumerable items, ushort order) => (ushort)(items.Where(q => q.Order == order) .Select(q => (int)q.Variant).DefaultIfEmpty(-1).Max() + 1); internal static (ushort Order, ushort Variant) GetOrderAndVariant(IEnumerable episodes, ushort? order = null, ushort? variant = null) { if (!order.HasValue) order = GetNewOrder(episodes); else if (order < 0 || order > episodes.Select(q => q.Order).DefaultIfEmpty((ushort)0).Max()) throw new ArgumentOutOfRangeException(nameof(order)); if (!variant.HasValue) variant ??= GetNewVariant(episodes, order.Value); else if (variant < 0 || variant > episodes.Select(q => q.Variant).DefaultIfEmpty((ushort)0).Max()) throw new ArgumentOutOfRangeException(nameof(order)); return (order.Value, variant.Value); } /* internal protected void SortItems(IEnumerable items) => base.SortItems(items, SetVariantAction, SetOrderAction); */ private protected virtual void SetItemOrder(IEnumerable items, ushort lastOrder, ushort newOrder) { if (lastOrder < 0 || lastOrder >= items.Count()) throw new ArgumentOutOfRangeException(nameof(lastOrder)); if (newOrder < 0 || newOrder >= items.Count()) throw new ArgumentOutOfRangeException(nameof(newOrder)); var minValue = Math.Min(lastOrder, newOrder); var maxValue = Math.Max(lastOrder, newOrder); var itemOrderGroups = items.GroupBy(q => q.Order) .Select(q => new { Order = q.Key, Items = items.Where(x => x.Order == q.Key) .OrderBy(x => x.Variant).ToList() }) .Where(q => q.Order >= minValue && q.Order <= maxValue).ToList(); var targetItem = itemOrderGroups.First(q => q.Order == newOrder); bool seen = false; for (int i = 0; i < itemOrderGroups.Count; i++) { if (object.ReferenceEquals(itemOrderGroups[i], targetItem)) { itemOrderGroups[i].Items.ForEach(q => q.Order = newOrder); //itemOrderGroups[i].Order = newOrder; seen = true; } else if (seen && itemOrderGroups[i].Order <= newOrder) { itemOrderGroups[i].Items.ForEach(q => q.Order = (ushort)(itemOrderGroups[i].Order - 1)); //orderedItems[i].Order--;// move it left } else if (itemOrderGroups[i].Order >= newOrder) { itemOrderGroups[i].Items.ForEach(q => q.Order = (ushort)(itemOrderGroups[i].Order + 1)); //orderedItems[i].Order++; // move it right } } } private protected virtual void SetItemVariant(IEnumerable items, ushort order, ushort lastVariant, ushort newVariant) { if (order < 0 || order >= items.GroupBy(q => q.Order).Count()) throw new ArgumentOutOfRangeException(nameof(order)); var variantItems = items.Where(q => q.Order == order).ToList(); if (lastVariant < 0 || lastVariant >= variantItems.Count()) throw new ArgumentOutOfRangeException(nameof(lastVariant)); if (newVariant < 0 || newVariant >= variantItems.Count()) throw new ArgumentOutOfRangeException(nameof(newVariant)); var minValue = Math.Min(lastVariant, newVariant); var maxValue = Math.Max(lastVariant, newVariant); var orderedItems = variantItems.Where(q => q.Variant >= minValue && q.Variant <= maxValue).ToList(); var targetItem = orderedItems.First(q => q.Variant == newVariant); bool seen = false; for (int i = 0; i < orderedItems.Count; i++) { if (object.ReferenceEquals(orderedItems[i], targetItem)) { orderedItems[i].Variant = newVariant; seen = true; } else if (seen && orderedItems[i].Variant <= newVariant) { orderedItems[i].Variant--;// move it left } else if (orderedItems[i].Variant >= newVariant) { orderedItems[i].Variant++; // move it right } } } public virtual void SetCompleted() => StructureAction(() => Completed = true); public virtual void SetNotCompleted() => StructureAction(() => Completed = true); public virtual void SetExpirationTime(TimeSpan value) => StructureAction(() => ExpirationTime = value); public virtual void Delete() => StructureAction(() => Deleted = true); protected abstract void StructureAction(Action action); }