using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using PkmnLibSharp.FFI; using PkmnLibSharp.Utils; namespace PkmnLibSharp.StaticData.Libraries { public abstract class DataLibrary : ExternPointer.CacheData>, IReadOnlyDictionary { protected DataLibrary(IdentifiablePointer ptr, bool isOwner) : base(ptr, isOwner) { } public class CacheData { public List? KeyCache { get; internal set; } public Dictionary ValueCache { get; } = new(); } public abstract void Add(string key, T value); public abstract int Count { get; } protected abstract T? GetValueByKey(string key); public bool ContainsKey(string key) { return GetValueByKey(key) != null; } public bool TryGetValue(string key, [NotNullWhen(true)] out T value) { if (Cache.ValueCache.TryGetValue(key, out value) && value != null) return true; var v = GetValueByKey(key); if (v != null) { Cache.ValueCache.Add(key, v); value = v; } return v != null; } public T this[string key] { get { if (!TryGetValue(key, out var value)) throw new KeyNotFoundException($"Value with key `{key}` was not found"); return value!; } } public abstract string? GetKeyByIndex(ulong index); public IEnumerable Keys { get { if (Cache.KeyCache == null) { Cache.KeyCache = new List(Count); for (ulong i = 0; i < (ulong)Count; i++) { var key = GetKeyByIndex(i); if (key == null) break; Cache.KeyCache.Add(key); } } return Cache.KeyCache; } } public IEnumerable Values { get { return Keys.Select(key => this[key]); } } protected override CacheData CreateCache() => new(); public IEnumerator> GetEnumerator() { return Keys.Select(key => new KeyValuePair(key, this[key])).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } ~DataLibrary() { Dispose(); } } }