using System;
using System.Collections.Generic;
using System.Threading;
namespace Crestron.SimplSharp
{
///
/// Mock implementation of Crestron CrestronQueue for testing purposes
/// Provides the same public API surface as the real CrestronQueue
///
/// Type of items in the queue
public class CrestronQueue : IDisposable
{
#region Private Fields
private readonly Queue _queue = new Queue();
private readonly object _lockObject = new object();
private readonly ManualResetEventSlim _dataAvailableEvent = new ManualResetEventSlim(false);
private bool _disposed = false;
#endregion
#region Properties
/// Gets the number of items in the queue
public int Count
{
get
{
lock (_lockObject)
{
return _queue.Count;
}
}
}
/// Gets whether the queue is empty
public bool IsEmpty
{
get
{
lock (_lockObject)
{
return _queue.Count == 0;
}
}
}
#endregion
#region Constructor
/// Initializes a new instance of the CrestronQueue class
public CrestronQueue()
{
// Mock implementation
}
/// Initializes a new instance of the CrestronQueue class with specified capacity
/// The initial capacity of the queue
public CrestronQueue(int capacity)
{
// Mock implementation - capacity is ignored in this mock
}
#endregion
#region Public Methods
/// Adds an item to the end of the queue
/// Item to add
public void Enqueue(T item)
{
if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue));
lock (_lockObject)
{
_queue.Enqueue(item);
_dataAvailableEvent.Set();
}
}
/// Removes and returns the item at the beginning of the queue
/// The item that was removed from the queue
/// Thrown when the queue is empty
public T Dequeue()
{
if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue));
lock (_lockObject)
{
if (_queue.Count == 0)
throw new InvalidOperationException("Queue is empty");
var item = _queue.Dequeue();
if (_queue.Count == 0)
_dataAvailableEvent.Reset();
return item;
}
}
/// Tries to remove and return the item at the beginning of the queue
/// When successful, contains the dequeued item
/// True if an item was successfully dequeued
public bool TryDequeue(out T item)
{
if (_disposed)
{
item = default(T)!;
return false;
}
lock (_lockObject)
{
if (_queue.Count == 0)
{
item = default(T)!;
return false;
}
item = _queue.Dequeue();
if (_queue.Count == 0)
_dataAvailableEvent.Reset();
return true;
}
}
/// Returns the item at the beginning of the queue without removing it
/// The item at the beginning of the queue
/// Thrown when the queue is empty
public T Peek()
{
if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue));
lock (_lockObject)
{
if (_queue.Count == 0)
throw new InvalidOperationException("Queue is empty");
return _queue.Peek();
}
}
/// Tries to return the item at the beginning of the queue without removing it
/// When successful, contains the item at the beginning of the queue
/// True if an item was found
public bool TryPeek(out T item)
{
if (_disposed)
{
item = default(T)!;
return false;
}
lock (_lockObject)
{
if (_queue.Count == 0)
{
item = default(T)!;
return false;
}
item = _queue.Peek();
return true;
}
}
/// Removes all items from the queue
public void Clear()
{
if (_disposed) return;
lock (_lockObject)
{
_queue.Clear();
_dataAvailableEvent.Reset();
}
}
/// Waits for data to become available in the queue
/// Timeout in milliseconds
/// True if data became available within the timeout
public bool WaitForData(int timeout)
{
if (_disposed) return false;
return _dataAvailableEvent.Wait(timeout);
}
/// Waits for data to become available in the queue
/// True when data becomes available
public bool WaitForData()
{
if (_disposed) return false;
_dataAvailableEvent.Wait();
return true;
}
/// Copies the queue elements to an array
/// Array containing the queue elements
public T[] ToArray()
{
if (_disposed) return new T[0];
lock (_lockObject)
{
return _queue.ToArray();
}
}
#endregion
#region IDisposable Implementation
/// Disposes the queue and releases resources
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// Protected dispose method
/// True if disposing managed resources
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_dataAvailableEvent?.Dispose();
Clear();
}
_disposed = true;
}
}
#endregion
}
}