using System;
using PepperDash.Core;
using Serilog.Events;
using System.Collections.Generic;
using System.Linq;
namespace PepperDash.Essentials.Core;
///
/// A collection of RouteDescriptors - typically the static DefaultCollection is used
///
public class RouteDescriptorCollection
{
///
/// The static default collection of RouteDescriptors. This is typically used for global routing management across the system, but additional collections could be used for specific purposes if desired.
///
public static RouteDescriptorCollection DefaultCollection
{
get
{
if (_DefaultCollection == null)
_DefaultCollection = new RouteDescriptorCollection();
return _DefaultCollection;
}
}
private static RouteDescriptorCollection _DefaultCollection;
private readonly List RouteDescriptors = new List();
///
/// Event raised when the collection of RouteDescriptors changes (add/remove). This is useful for updating routing status in the UI, for example.
///
public event EventHandler RouteDescriptorCollectionChanged;
///
/// Gets an enumerable collection of all RouteDescriptors in this collection.
///
public IEnumerable Descriptors => RouteDescriptors.AsReadOnly();
///
/// Adds a RouteDescriptor to the list. If an existing RouteDescriptor for the
/// destination exists already, it will not be added - in order to preserve
/// proper route releasing.
///
///
public void AddRouteDescriptor(RouteDescriptor descriptor)
{
if (descriptor == null)
{
return;
}
// Check if a route already exists with the same source, destination, input port, AND signal type
var existingRoute = RouteDescriptors.FirstOrDefault(t =>
t.Source == descriptor.Source &&
t.Destination == descriptor.Destination &&
t.SignalType == descriptor.SignalType &&
((t.InputPort == null && descriptor.InputPort == null) ||
(t.InputPort != null && descriptor.InputPort != null && t.InputPort.Key == descriptor.InputPort.Key)));
if (existingRoute != null)
{
Debug.LogMessage(LogEventLevel.Information, descriptor.Destination,
"Route from {0} to {1}:{2} ({3}) already exists in this collection",
descriptor?.Source?.Key,
descriptor?.Destination?.Key,
descriptor?.InputPort?.Key ?? "auto",
descriptor?.SignalType);
return;
}
Debug.LogMessage(LogEventLevel.Verbose, "Adding route descriptor: {0} -> {1}:{2} ({3})",
descriptor?.Source?.Key,
descriptor?.Destination?.Key,
descriptor?.InputPort?.Key ?? "auto",
descriptor?.SignalType);
RouteDescriptors.Add(descriptor);
RouteDescriptorCollectionChanged?.Invoke(this, EventArgs.Empty);
}
///
/// Gets the RouteDescriptor for a destination
///
/// null if no RouteDescriptor for a destination exists
public RouteDescriptor GetRouteDescriptorForDestination(IRoutingInputs destination)
{
Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}'", destination?.Key ?? null);
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination);
}
///
/// Gets the route descriptor for a specific destination and input port
///
/// The destination device
/// The input port key
/// The matching RouteDescriptor or null if not found
public RouteDescriptor GetRouteDescriptorForDestinationAndInputPort(IRoutingInputs destination, string inputPortKey)
{
Debug.LogMessage(LogEventLevel.Information, "Getting route descriptor for '{destination}':'{inputPortKey}'", destination?.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
return RouteDescriptors.FirstOrDefault(rd => rd.Destination == destination && rd.InputPort != null && rd.InputPort.Key == inputPortKey);
}
///
/// Returns the RouteDescriptor for a given destination AND removes it from collection.
/// Returns null if no route with the provided destination exists.
///
/// The destination device
/// The input port key (optional)
/// The matching RouteDescriptor or null if not found
public RouteDescriptor RemoveRouteDescriptor(IRoutingInputs destination, string inputPortKey = "")
{
Debug.LogMessage(LogEventLevel.Information, "Removing route descriptor for '{destination}':'{inputPortKey}'", destination.Key ?? null, string.IsNullOrEmpty(inputPortKey) ? "auto" : inputPortKey);
var descr = string.IsNullOrEmpty(inputPortKey)
? GetRouteDescriptorForDestination(destination)
: GetRouteDescriptorForDestinationAndInputPort(destination, inputPortKey);
if (descr != null)
{
RouteDescriptors.Remove(descr);
RouteDescriptorCollectionChanged?.Invoke(this, EventArgs.Empty);
}
Debug.LogMessage(LogEventLevel.Information, "Found route descriptor {routeDescriptor}", destination, descr);
return descr;
}
}