#nullable enable
using System.Collections.Concurrent;
namespace Terminal.Gui.Drivers;
///
/// Interface for reading console input in a perpetual loop on a dedicated input thread.
///
///
///
/// Implementations run on a separate thread (started by
/// )
/// and continuously read platform-specific input from the console, placing it into a thread-safe queue
/// for processing by on the main UI thread.
///
///
/// Architecture:
///
///
/// Input Thread: Main UI Thread:
/// ┌─────────────────┐ ┌──────────────────────┐
/// │ IInput.Run() │ │ IInputProcessor │
/// │ ├─ Peek() │ │ ├─ ProcessQueue() │
/// │ ├─ Read() │──Enqueue──→ │ ├─ Process() │
/// │ └─ Enqueue │ │ ├─ ToKey() │
/// └─────────────────┘ │ └─ Raise Events │
/// └──────────────────────┘
///
///
/// Lifecycle:
///
///
/// - - Set the shared input queue
/// - - Start the perpetual read loop (blocks until cancelled)
/// -
/// Loop calls and
///
/// - Cancellation via `runCancellationToken` or
///
///
/// Implementations:
///
///
/// - - Uses Windows Console API (ReadConsoleInput)
/// - - Uses .NET API
/// - - Uses Unix terminal APIs
/// - - For testing, implements
///
///
/// Testing Support: See for programmatic input injection
/// in test scenarios.
///
///
///
/// The platform-specific input record type:
///
/// - - for .NET and Fake drivers
/// - - for Windows driver
/// - - for Unix driver
///
///
public interface IInput : IDisposable
{
///
/// Gets or sets an external cancellation token source that can stop the loop
/// in addition to the `runCancellationToken` passed to .
///
///
///
/// This property allows external code (e.g., test harnesses like GuiTestContext) to
/// provide additional cancellation signals such as timeouts or hard-stop conditions.
///
///
/// Ownership: The setter does NOT transfer ownership of the .
/// The creator is responsible for disposal. implementations
/// should NOT dispose this token source.
///
///
/// How it works: creates a linked token that
/// responds to BOTH the `runCancellationToken` AND this external token:
///
///
/// var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(
/// runCancellationToken,
/// ExternalCancellationTokenSource.Token);
///
///
///
/// Test scenario with timeout:
///
/// var input = new FakeInput();
/// input.ExternalCancellationTokenSource = new CancellationTokenSource(
/// TimeSpan.FromSeconds(30)); // 30-second timeout
///
/// // Run will stop if either:
/// // 1. runCancellationToken is cancelled (normal shutdown)
/// // 2. 30 seconds elapse (timeout)
/// input.Run(normalCancellationToken);
///
///
CancellationTokenSource? ExternalCancellationTokenSource { get; set; }
///
/// Initializes the input reader with the thread-safe queue where read input will be stored.
///
///
/// The shared that both (producer)
/// and (consumer) use for passing input records between threads.
///
///
///
/// This queue is created by
/// and shared between the input thread and main UI thread.
///
///
/// Must be called before . Calling without
/// initialization will throw an exception.
///
///
void Initialize (ConcurrentQueue inputQueue);
///
/// Runs the input loop, continuously reading input and placing it into the queue
/// provided by .
///
///
/// The primary cancellation token that stops the input loop. Provided by
/// and triggered
/// during application shutdown.
///
///
///
/// Threading: This method runs on a dedicated input thread created by
/// . and blocks until
/// cancellation is requested. It should never be called from the main UI thread.
///
///
/// Cancellation: The loop stops when either
/// or (if set) is cancelled.
///
///
/// Base Implementation: provides the
/// standard loop logic:
///
///
/// while (!cancelled)
/// {
/// while (Peek()) // Check for available input
/// {
/// foreach (var input in Read()) // Read all available
/// {
/// inputQueue.Enqueue(input); // Store for processing
/// }
/// }
/// Task.Delay(20ms); // Throttle to ~50 polls/second
/// }
///
///
/// Testing: For implementations,
/// test input injected via
/// flows through the same Peek/Read pipeline.
///
///
///
/// Thrown when or
/// is cancelled. This is the normal/expected means of exiting the input loop.
///
///
/// Thrown if was not called before .
///
void Run (CancellationToken runCancellationToken);
}