using System; using System.Collections.Generic; namespace DanieleMarotta.RiversongCodeShowcase { public class EntityCollection : IEntityCollection { private static readonly List Empty = new(); private int _nextId = Entity.InvalidId + 1; private Dictionary _entitiesById = new(); private ListMultiDictionary _entitiesByType = new(); private Dictionary _callbacks = new(); public T Create() where T : Entity, new() { return Entity.Create(_nextId++); } public void Add(Entity entity) { _entitiesById.Add(entity.Id, entity); OnAdded(entity.GetType(), entity); } private void OnAdded(Type type, Entity entity) { _entitiesByType.Add(type, entity); if (_callbacks.TryGetValue(type, out var callbacks)) callbacks.OnAdded(entity); if (type == typeof(Entity)) return; OnAdded(type.BaseType, entity); } public Entity Remove(int id) { if (!_entitiesById.Remove(id, out var entity)) return null; OnRemoved(entity.GetType(), entity); return entity; } private void OnRemoved(Type type, Entity entity) { _entitiesByType.Remove(type, entity); if (_callbacks.TryGetValue(type, out var callbacks)) callbacks.OnRemoved(entity); if (type == typeof(Entity)) return; OnRemoved(type.BaseType, entity); } public bool Exists(int id) { return _entitiesById.ContainsKey(id); } public Entity Get(int id) { return _entitiesById.TryGetValue(id, out var entity) ? entity : null; } public Type GetEntityType(int id) { return Get(id)?.GetType(); } public List GetInternalEntityList(Type type) { return _entitiesByType.TryGetValues(type, out var entityList) ? entityList : Empty; } public IEntityCollectionCallbacks On() where T : Entity { if (!_callbacks.TryGetValue(typeof(T), out var callbacks)) { callbacks = new EntityCollectionCallbacks(); _callbacks.Add(typeof(T), callbacks); } return (IEntityCollectionCallbacks)callbacks; } } }