using System; using System.Collections.Generic; using System.Linq; namespace MxGateway.Worker.MxAccess; public sealed class MxAccessHandleRegistry { private readonly Dictionary serverHandles = new(); private readonly Dictionary itemHandles = new(); private readonly Dictionary adviceHandles = new(); public IReadOnlyList ServerHandles => serverHandles .Values .OrderBy(handle => handle.ServerHandle) .ToArray(); public IReadOnlyList ItemHandles => itemHandles .Values .OrderBy(handle => handle.ServerHandle) .ThenBy(handle => handle.ItemHandle) .ToArray(); public IReadOnlyList AdviceHandles => adviceHandles .Values .OrderBy(handle => handle.ServerHandle) .ThenBy(handle => handle.ItemHandle) .ThenBy(handle => handle.AdviceKind) .ToArray(); public void RegisterServerHandle( int serverHandle, string clientName) { serverHandles[serverHandle] = new RegisteredServerHandle(serverHandle, clientName); } public void UnregisterServerHandle(int serverHandle) { serverHandles.Remove(serverHandle); foreach (long key in itemHandles .Where(pair => pair.Value.ServerHandle == serverHandle) .Select(pair => pair.Key) .ToArray()) { itemHandles.Remove(key); } foreach (AdviceHandleKey key in adviceHandles .Where(pair => pair.Value.ServerHandle == serverHandle) .Select(pair => pair.Key) .ToArray()) { adviceHandles.Remove(key); } } public bool ContainsServerHandle(int serverHandle) { return serverHandles.ContainsKey(serverHandle); } public void RegisterItemHandle( int serverHandle, int itemHandle, string itemDefinition, string itemContext, bool hasItemContext) { itemHandles[CreateItemKey(serverHandle, itemHandle)] = new RegisteredItemHandle( serverHandle, itemHandle, itemDefinition, itemContext, hasItemContext); } public void RemoveItemHandle( int serverHandle, int itemHandle) { itemHandles.Remove(CreateItemKey(serverHandle, itemHandle)); RemoveAdviceHandles(serverHandle, itemHandle); } public bool ContainsItemHandle( int serverHandle, int itemHandle) { return itemHandles.ContainsKey(CreateItemKey(serverHandle, itemHandle)); } public void RegisterAdviceHandle( int serverHandle, int itemHandle, MxAccessAdviceKind adviceKind) { AdviceHandleKey key = new(serverHandle, itemHandle, adviceKind); adviceHandles[key] = new RegisteredAdviceHandle( serverHandle, itemHandle, adviceKind); } public void RemoveAdviceHandles( int serverHandle, int itemHandle) { foreach (AdviceHandleKey key in adviceHandles .Where(pair => pair.Value.ServerHandle == serverHandle && pair.Value.ItemHandle == itemHandle) .Select(pair => pair.Key) .ToArray()) { adviceHandles.Remove(key); } } public bool ContainsAdviceHandle( int serverHandle, int itemHandle, MxAccessAdviceKind adviceKind) { return adviceHandles.ContainsKey(new AdviceHandleKey(serverHandle, itemHandle, adviceKind)); } private static long CreateItemKey( int serverHandle, int itemHandle) { return ((long)serverHandle << 32) | (uint)itemHandle; } private readonly struct AdviceHandleKey : IEquatable { private readonly int serverHandle; private readonly int itemHandle; private readonly MxAccessAdviceKind adviceKind; public AdviceHandleKey( int serverHandle, int itemHandle, MxAccessAdviceKind adviceKind) { this.serverHandle = serverHandle; this.itemHandle = itemHandle; this.adviceKind = adviceKind; } public bool Equals(AdviceHandleKey other) { return serverHandle == other.serverHandle && itemHandle == other.itemHandle && adviceKind == other.adviceKind; } public override bool Equals(object? obj) { return obj is AdviceHandleKey other && Equals(other); } public override int GetHashCode() { unchecked { int hashCode = serverHandle; hashCode = (hashCode * 397) ^ itemHandle; hashCode = (hashCode * 397) ^ (int)adviceKind; return hashCode; } } } }