using System;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using Swan.Threading;
namespace Swan {
///
/// A console terminal helper to create nicer output and receive input from the user.
/// This class is thread-safe :).
///
public static partial class Terminal {
#region Private Declarations
// [Obsolete("NEED", false)]
private const Int32 OutputFlushInterval = 15;
// [Obsolete("NEED", false)]
private static readonly ExclusiveTimer DequeueOutputTimer;
// [Obsolete("NEED", false)]
private static readonly Object SyncLock = new Object();
// [Obsolete("NEED", false)]
private static readonly ConcurrentQueue OutputQueue = new ConcurrentQueue();
// [Obsolete("NEED", false)]
private static readonly ManualResetEventSlim OutputDone = new ManualResetEventSlim(false);
// [Obsolete("NEED", false)]
private static readonly ManualResetEventSlim InputDone = new ManualResetEventSlim(true);
// [Obsolete("NEED", false)]
private static Boolean? _isConsolePresent;
#endregion
#region Constructors
///
/// Initializes static members of the class.
///
// [Obsolete("NEED", false)]
static Terminal() {
lock(SyncLock) {
if(DequeueOutputTimer != null) {
return;
}
if(IsConsolePresent) {
Console.CursorVisible = false;
}
// Here we start the output task, fire-and-forget
DequeueOutputTimer = new ExclusiveTimer(DequeueOutputCycle);
DequeueOutputTimer.Resume(OutputFlushInterval);
}
}
///
/// Gets a value indicating whether the Console is present.
///
///
/// true if this instance is console present; otherwise, false.
///
// [Obsolete("NEED", false)]
public static Boolean IsConsolePresent {
get {
if(_isConsolePresent == null) {
_isConsolePresent = true;
try {
Int32 windowHeight = Console.WindowHeight;
_isConsolePresent = windowHeight >= 0;
} catch {
_isConsolePresent = false;
}
}
return _isConsolePresent.Value;
}
}
///
/// Gets the available output writers in a bitwise mask.
///
///
/// The available writers.
///
// [Obsolete("NEED", false)]
public static TerminalWriters AvailableWriters => IsConsolePresent ? TerminalWriters.StandardError | TerminalWriters.StandardOutput : TerminalWriters.None;
///
/// Gets or sets the output encoding for the current console.
///
///
/// The output encoding.
///
// [Obsolete("NEED", false)]
public static Encoding OutputEncoding {
get => Console.OutputEncoding;
set => Console.OutputEncoding = value;
}
#endregion
#region Methods
///
/// Enqueues the output to be written to the console
/// This is the only method that should enqueue to the output
/// Please note that if AvailableWriters is None, then no output will be enqueued.
///
/// The context.
// [Obsolete("NEED", false)]
private static void EnqueueOutput(OutputContext context) {
lock(SyncLock) {
TerminalWriters availableWriters = AvailableWriters;
if(availableWriters == TerminalWriters.None || context.OutputWriters == TerminalWriters.None) {
OutputDone.Set();
return;
}
if((context.OutputWriters & availableWriters) == TerminalWriters.None) {
return;
}
OutputDone.Reset();
OutputQueue.Enqueue(context);
}
}
///
/// Runs a Terminal I/O cycle in the thread.
///
// [Obsolete("NEED", false)]
private static void DequeueOutputCycle() {
if(AvailableWriters == TerminalWriters.None) {
OutputDone.Set();
return;
}
InputDone.Wait();
if(OutputQueue.Count <= 0) {
OutputDone.Set();
return;
}
OutputDone.Reset();
while(OutputQueue.Count > 0) {
if(!OutputQueue.TryDequeue(out OutputContext context)) {
continue;
}
// Process Console output and Skip over stuff we can't display so we don't stress the output too much.
if(!IsConsolePresent) {
continue;
}
Console.ForegroundColor = context.OutputColor;
// Output to the standard output
if(context.OutputWriters.HasFlag(TerminalWriters.StandardOutput)) {
Console.Out.Write(context.OutputText);
}
// output to the standard error
if(context.OutputWriters.HasFlag(TerminalWriters.StandardError)) {
Console.Error.Write(context.OutputText);
}
Console.ResetColor();
Console.ForegroundColor = context.OriginalColor;
}
}
#endregion
#region Output Context
///
/// Represents an asynchronous output context.
///
// [Obsolete("NEED", false)]
private sealed class OutputContext {
///
/// Initializes a new instance of the class.
///
public OutputContext() {
this.OriginalColor = Settings.DefaultColor;
this.OutputWriters = IsConsolePresent ? TerminalWriters.StandardOutput : TerminalWriters.None;
}
public ConsoleColor OriginalColor {
get;
}
public ConsoleColor OutputColor {
get; set;
}
public Char[] OutputText {
get; set;
}
public TerminalWriters OutputWriters {
get; set;
}
}
#endregion
}
}