using System.Collections.Concurrent; using System.Text.RegularExpressions; using MBN_STOCK_WEBVIEW.Playout.Configuration; using MBN_STOCK_WEBVIEW.Playout.Interop; using MBN_STOCK_WEBVIEW.Playout.Registration; using MBN_STOCK_WEBVIEW.Playout.Runtime; using MBN_STOCK_WEBVIEW.Playout.Safety; namespace MBN_STOCK_WEBVIEW.Playout.Tests; internal sealed class FakeK3dSessionFactory : IK3dSessionFactory { private readonly Func _create; private int _createCount; public FakeK3dSessionFactory(Func? create = null) { _create = create ?? (() => new FakeK3dSession()); } public int CreateCount => Volatile.Read(ref _createCount); public ConcurrentQueue Sessions { get; } = new(); public IK3dSession Create() { Interlocked.Increment(ref _createCount); var session = _create(); Sessions.Enqueue(session); return session; } } internal sealed class FakeK3dSession : IK3dSession { private int _disposed; public bool IsConnected { get; private set; } public ConcurrentQueue Calls { get; } = new(); public ConcurrentQueue ThreadIds { get; } = new(); public ConcurrentQueue ApartmentStates { get; } = new(); public Action? ConnectAction { get; set; } public Action? DisconnectAction { get; set; } public Action? PrepareAction { get; set; } public Action? PlayAction { get; set; } public Action? TakeOutAction { get; set; } public void Connect(ValidatedPlayoutOptions options) { Record("Connect"); ConnectAction?.Invoke(options); IsConnected = true; } public void Disconnect() { Record("Disconnect"); DisconnectAction?.Invoke(); IsConnected = false; } public void Prepare(PlayoutCue cue, int layoutIndex) { Record($"Prepare:{cue.SceneName}"); PrepareAction?.Invoke(cue, layoutIndex); } public void Play(int layoutIndex) { Record("Play"); PlayAction?.Invoke(layoutIndex); } public void TakeOut(int layoutIndex, PlayoutTakeOutScope scope) { Record($"TakeOut:{scope}"); TakeOutAction?.Invoke(layoutIndex, scope); } public void Dispose() { if (Interlocked.Exchange(ref _disposed, 1) == 0) { Record("Dispose"); IsConnected = false; } } private void Record(string name) { Calls.Enqueue(name); ThreadIds.Enqueue(Environment.CurrentManagedThreadId); ApartmentStates.Enqueue(Thread.CurrentThread.GetApartmentState()); } } internal sealed class FakeRegistrationProbe : IK3dRegistrationProbe { private int _probeCount; public FakeRegistrationProbe(K3dRegistrationReport? report = null) { Report = report ?? ReadyReport; } public static K3dRegistrationReport ReadyReport { get; } = new( K3dRegistrationIssue.None, Is64BitProcess: true, HasWin64TypeLibrary: true, IsWin64BinaryAmd64: true, IsEngineClassReady: true, IsEventHandlerClassReady: true, Message: "fake K3D registration ready"); public K3dRegistrationReport Report { get; set; } public int ProbeCount => Volatile.Read(ref _probeCount); public K3dRegistrationReport Probe() { Interlocked.Increment(ref _probeCount); return Report; } } internal sealed class FakeTornadoProcessProbe : ITornadoProcessProbe { private readonly object _sync = new(); private readonly Queue _snapshots = new(); private TornadoProcessSnapshot _last; public FakeTornadoProcessProbe(params TornadoProcessSnapshot[] snapshots) { _last = snapshots.LastOrDefault() ?? new TornadoProcessSnapshot(0, 0, 0); foreach (var snapshot in snapshots) { _snapshots.Enqueue(snapshot); } } public int CaptureCount { get; private set; } public Regex? LastPattern { get; private set; } public TornadoProcessSnapshot Capture(Regex? testWindowPattern) { lock (_sync) { CaptureCount++; LastPattern = testWindowPattern; if (_snapshots.Count > 0) { _last = _snapshots.Dequeue(); } return _last; } } } internal sealed class FakeLiveAuthorization : ILiveAuthorization { public FakeLiveAuthorization(bool isAuthorizedForThisLaunch) { IsAuthorizedForThisLaunch = isAuthorizedForThisLaunch; } public bool IsAuthorizedForThisLaunch { get; } } internal sealed class TrackingStaDispatcherFactory : IStaDispatcherFactory { private int _createCount; public int CreateCount => Volatile.Read(ref _createCount); public ConcurrentQueue Dispatchers { get; } = new(); public IStaDispatcher Create(int capacity) { Interlocked.Increment(ref _createCount); var dispatcher = new StaDispatcher(capacity); Dispatchers.Enqueue(dispatcher); return dispatcher; } }