#nullable disable using NadekoBot.Services.Database.Models; using System.Collections; namespace NadekoBot.Common.Collections; public class IndexedCollection : IList where T : class, IIndexed { public List Source { get; } public int Count => Source.Count; public bool IsReadOnly => false; public virtual T this[int index] { get => Source[index]; set { lock (_locker) { value.Index = index; Source[index] = value; } } } private readonly object _locker = new(); public IndexedCollection() => Source = new(); public IndexedCollection(IEnumerable source) { lock (_locker) { Source = source.OrderBy(x => x.Index).ToList(); UpdateIndexes(); } } public int IndexOf(T item) => item?.Index ?? -1; public IEnumerator GetEnumerator() => Source.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => Source.GetEnumerator(); public void Add(T item) { ArgumentNullException.ThrowIfNull(item); lock (_locker) { item.Index = Source.Count; Source.Add(item); } } public virtual void Clear() { lock (_locker) { Source.Clear(); } } public bool Contains(T item) { lock (_locker) { return Source.Contains(item); } } public void CopyTo(T[] array, int arrayIndex) { lock (_locker) { Source.CopyTo(array, arrayIndex); } } public virtual bool Remove(T item) { lock (_locker) { if (Source.Remove(item)) { for (var i = 0; i < Source.Count; i++) { if (Source[i].Index != i) Source[i].Index = i; } return true; } } return false; } public virtual void Insert(int index, T item) { lock (_locker) { Source.Insert(index, item); for (var i = index; i < Source.Count; i++) Source[i].Index = i; } } public virtual void RemoveAt(int index) { lock (_locker) { Source.RemoveAt(index); for (var i = index; i < Source.Count; i++) Source[i].Index = i; } } public void UpdateIndexes() { lock (_locker) { for (var i = 0; i < Source.Count; i++) { if (Source[i].Index != i) Source[i].Index = i; } } } public static implicit operator List(IndexedCollection x) => x.Source; public List ToList() => Source.ToList(); }