using System.Collections; using PkmnLib.Dynamic.ScriptHandling.Registry; using PkmnLib.Static.Utils; namespace PkmnLib.Dynamic.ScriptHandling; /// /// 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. /// public interface IScriptSet : IEnumerable { /// /// 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. /// ScriptContainer Add(Script script); /// /// 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. /// ScriptContainer? StackOrAdd(StringKey scriptKey, Func instantiation); /// /// Gets a script from the set using its unique name. /// ScriptContainer? Get(StringKey scriptKey); /// /// Gets a script from the set using its type. /// T? Get() where T : Script; /// /// Removes a script from the set using its unique name. /// void Remove(StringKey scriptKey); /// /// Clears all scripts from the set. /// void Clear(); /// /// Checks if the set has a script with the given type. /// bool Contains() where T : Script => Contains(ScriptUtils.ResolveName()); /// /// Checks if the set has a script with the given name. /// bool Contains(StringKey scriptKey); /// /// Gets a script from the set at a specific index. /// ScriptContainer At(int index); /// /// Gets the number of scripts in the set. /// int Count { get; } /// /// Gets the names of all scripts in the set. /// IEnumerable GetScriptNames(); } /// public class ScriptSet : IScriptSet { private readonly List _scripts = []; /// public IEnumerator GetEnumerator() => _scripts.GetEnumerator(); /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// public ScriptContainer Add(Script script) { var existing = _scripts.FirstOrDefault(s => s.Script?.Name == script.Name); if (existing != null) { existing.Script!.Stack(); return existing; } script.OnRemoveEvent += s => Remove(s.Name); var container = new ScriptContainer(script); _scripts.Add(container); return container; } /// public ScriptContainer? StackOrAdd(StringKey scriptKey, Func 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; script.OnRemoveEvent += s => Remove(s.Name); var container = new ScriptContainer(script); _scripts.Add(container); return container; } /// public ScriptContainer? Get(StringKey scriptKey) => _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey); /// public T? Get() where T : Script => Get(ScriptUtils.ResolveName())?.Script as T; /// public void Remove(StringKey scriptKey) { var script = _scripts.FirstOrDefault(s => s.Script?.Name == scriptKey); if (script is null) return; script.Script?.OnRemove(); _scripts.Remove(script); } /// public void Clear() { foreach (var script in _scripts) { if (!script.IsEmpty) { script.Script.OnRemove(); } } _scripts.Clear(); } /// public bool Contains(StringKey scriptKey) => _scripts.Any(s => s.Script?.Name == scriptKey); /// public ScriptContainer At(int index) => _scripts[index]; /// public int Count => _scripts.Count; /// public IEnumerable GetScriptNames() => _scripts.Select(x => x.Script).WhereNotNull().Select(s => s.Name); }