using Newtonsoft.Json;
using RhythmBase.Events;
using System.Collections;
namespace RhythmBase.Components
{
///
/// A collection of events that maintains the sequence of events.
///
public abstract class OrderedEventCollection : ICollection
{
///
/// Gets the total count of events in the collection.
///
[JsonIgnore]
public virtual int Count => eventsBeatOrder.Sum((i) => i.Value.Count());
///
/// Gets a value indicating whether the collection is read-only.
///
[JsonIgnore]
public bool IsReadOnly { get; }
///
/// Returns the beat of the last event.
///
/// The beat of the last event.
[JsonIgnore]
public RDBeat Length => eventsBeatOrder.LastOrDefault().Value.FirstOrDefault()?.Beat??new();
///
/// Initializes a new instance of the class.
///
public OrderedEventCollection()
{
eventsBeatOrder = [];
IsReadOnly = false;
}
///
/// Initializes a new instance of the class with the specified items.
///
/// The items to add to the collection.
public OrderedEventCollection(IEnumerable items)
{
eventsBeatOrder = [];
IsReadOnly = false;
foreach (IBaseEvent item in items)
Add(item);
}
///
/// Concatenates all events in the collection.
///
/// A list of all events in the collection.
public IEnumerable ConcatAll() => eventsBeatOrder.SelectMany(i => i.Value).ToList();
///
/// Adds an event to the collection.
///
/// The event to add.
public void Add(IBaseEvent item)
{
TypedEventCollection list = [];
if (eventsBeatOrder.TryGetValue(item.Beat, out TypedEventCollection? value))
list = value;
else
eventsBeatOrder.Add(item.Beat, list);
list.Add(item);
}
///
/// Clears all events from the collection.
///
public void Clear() => eventsBeatOrder.Clear();
///
/// Determines whether the collection contains a specific event.
///
/// The event to locate in the collection.
/// true if the event is found in the collection; otherwise, false.
public virtual bool Contains(IBaseEvent item) => eventsBeatOrder.ContainsKey(item.Beat) && eventsBeatOrder[item.Beat].Contains(item);
///
/// Copies the elements of the collection to an array, starting at a particular array index.
///
/// The array to copy the elements to.
/// The zero-based index in the array at which copying begins.
public void CopyTo(IBaseEvent[] array, int arrayIndex)
{
ArgumentNullException.ThrowIfNull(array);
if (arrayIndex < 0 || arrayIndex > array.Length)
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (array.Length - arrayIndex < Count)
throw new ArgumentException("The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array.");
foreach (var pair in eventsBeatOrder)
{
foreach (var item in pair.Value)
{
array[arrayIndex++] = item;
}
}
}
///
/// Removes the first occurrence of a specific event from the collection.
///
/// The event to remove from the collection.
/// true if the event was successfully removed; otherwise, false.
internal bool Remove(IBaseEvent item)
{
bool Remove;
if (Contains(item))
{
bool result = eventsBeatOrder[item.Beat].Remove(item);
if (!eventsBeatOrder[item.Beat].Any())
eventsBeatOrder.Remove(item.Beat);
Remove = result;
}
else
Remove = false;
return Remove;
}
///
/// Returns an enumerator that iterates through the collection.
///
/// An enumerator for the collection.
public IEnumerator GetEnumerator()
{
foreach (KeyValuePair> pair in eventsBeatOrder)
foreach (IBaseEvent item in pair.Value)
yield return item;
}
///
/// Returns an enumerator that iterates through the collection.
///
/// An enumerator for the collection.
IEnumerator IEnumerable.GetEnumerator()
{
foreach (KeyValuePair> pair in eventsBeatOrder)
foreach (IBaseEvent item in pair.Value)
yield return item;
}
///
/// Returns a string that represents the current object.
///
/// A string that represents the current object.
public override string ToString() => string.Format("Count = {0}", Count);
///
/// Removes the first occurrence of a specific event from the collection.
///
/// The event to remove from the collection.
/// true if the event was successfully removed; otherwise, false.
bool ICollection.Remove(IBaseEvent item) => throw new NotImplementedException();
///
/// The dictionary that maintains the order of events based on their beats.
///
internal SortedDictionary> eventsBeatOrder;
}
}