using System.Collections; using PkmnLib.Static.Utils; namespace PkmnLib.Dynamic.ScriptHandling; /// <summary> /// A script set is a collection of scripts that can be accessed by a key. /// We can add, remove, and clear scripts from the set. /// This is generally used for volatile scripts. /// </summary> public interface IScriptSet : IEnumerable<ScriptContainer> { /// <summary> /// Adds a script to the set. If the script with that name already exists in this set, this /// makes that script stack instead. The return value here is that script. /// </summary> ScriptContainer Add(Script script); /// <summary> /// Adds a script with a name to the set. If the script with that name already exists in this /// set, this makes that script stack instead. The return value here is that script. /// </summary> ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script> instantiation); /// <summary> /// Gets a script from the set using its unique name. /// </summary> ScriptContainer? Get(StringKey scriptKey); /// <summary> /// Removes a script from the set using its unique name. /// </summary> void Remove(StringKey scriptKey); /// <summary> /// Clears all scripts from the set. /// </summary> void Clear(); /// <summary> /// Checks if the set has a script with the given name. /// </summary> bool Contains(StringKey scriptKey); /// <summary> /// Gets a script from the set at a specific index. /// </summary> ScriptContainer At(int index); /// <summary> /// Gets the number of scripts in the set. /// </summary> int Count { get; } /// <summary> /// Gets the names of all scripts in the set. /// </summary> IEnumerable<StringKey> GetScriptNames(); } /// <inheritdoc cref="IScriptSet"/> public class ScriptSet : IScriptSet { private readonly List<ScriptContainer> _scripts = []; /// <inheritdoc /> public IEnumerator<ScriptContainer> GetEnumerator() => _scripts.GetEnumerator(); /// <inheritdoc /> IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// <inheritdoc /> public ScriptContainer Add(Script script) { var existing = _scripts.FirstOrDefault(s => s.Script?.Name == script.Name); if (existing != null) { existing.Script!.Stack(); return existing; } var container = new ScriptContainer(script); _scripts.Add(container); return container; } /// <inheritdoc /> public ScriptContainer? StackOrAdd(StringKey scriptKey, Func<Script?> instantiation) { var existing = _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey); if (existing != null) { existing.Script!.Stack(); return existing; } var script = instantiation(); if (script is null) return null; var container = new ScriptContainer(script); _scripts.Add(container); return container; } /// <inheritdoc /> public ScriptContainer? Get(StringKey scriptKey) => _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey); /// <inheritdoc /> public void Remove(StringKey scriptKey) { var script = _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey); if (script is null) return; _scripts.Remove(script); } /// <inheritdoc /> public void Clear() { foreach (var script in _scripts) { if (!script.IsEmpty) { script.Script.OnRemove(); } } _scripts.Clear(); } /// <inheritdoc /> public bool Contains(StringKey scriptKey) => _scripts.Any(s => s.Script?.Name == scriptKey); /// <inheritdoc /> public ScriptContainer At(int index) => _scripts[index]; /// <inheritdoc /> public int Count => _scripts.Count; /// <inheritdoc /> public IEnumerable<StringKey> GetScriptNames() => _scripts .Select(x => x.Script) .WhereNotNull() .Select(s => s.Name); }