using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tango.Transport.Adapters
{
///
/// Represents an in-memory transport adapter.
///
///
public class MemoryTransportAdapter : TransportAdapterBase
{
#region Memory Transport Manager
internal static class MemoryTransportManager
{
private static List _adapters;
static MemoryTransportManager()
{
_adapters = new List();
}
internal static void Connect(MemoryTransportAdapter adapter)
{
if (adapter == null)
{
throw new NullReferenceException("Cannot connect null adapter.");
}
if (String.IsNullOrWhiteSpace(adapter.Address))
{
throw new InvalidOperationException("Cannot register a memory adapter with null address.");
}
if (_adapters.Where(x => x.Address == adapter.Address).Count() > 1)
{
throw new InvalidOperationException("Cannot register more than two memory adapters with the same address.");
}
if (_adapters.Contains(adapter))
{
throw new InvalidOperationException("The specified memory adapter is already registered.");
}
_adapters.Add(adapter);
}
internal static void Disconnect(MemoryTransportAdapter adapter)
{
if (adapter == null)
{
throw new NullReferenceException("Cannot disconnect null adapter.");
}
_adapters.Remove(adapter);
}
internal static void Write(MemoryTransportAdapter adapter, byte[] data)
{
Task.Factory.StartNew(() =>
{
var other_adapter = _adapters.ToList().SingleOrDefault(x => x.Address == adapter.Address && x != adapter);
if (other_adapter != null)
{
other_adapter.EmulateDataAvailable(data);
}
});
}
}
#endregion
///
/// Initializes a new instance of the class.
///
/// The address.
public MemoryTransportAdapter(String address)
{
ComponentName = $"In-Memory Adapter {_component_counter++}";
Address = address;
}
///
/// Emulates in coming data.
///
/// The data.
internal void EmulateDataAvailable(byte[] data)
{
OnDataAvailable(data);
}
///
/// Writes the specified data to the stream.
///
/// The data.
public override void Write(byte[] data, bool immidiate = false)
{
ThrowIfDisposed();
try
{
TotalBytesSent += data.Length;
_totalBytes += data.Length;
MemoryTransportManager.Write(this, data);
}
catch (Exception ex)
{
OnFailed(LogManager.Log(ex));
}
}
///
/// Connects the transport component.
///
///
public override Task Connect()
{
MemoryTransportManager.Connect(this);
State = TransportComponentState.Connected;
return Task.FromResult(new object());
}
///
/// Disconnects the transport component.
///
///
public override Task Disconnect()
{
MemoryTransportManager.Disconnect(this);
State = TransportComponentState.Disconnected;
return Task.FromResult(new object());
}
}
}