using System;
using System.Collections.Generic;
using System.Linq;
using Crestron.SimplSharpPro;
using PepperDash.Core;
using Serilog.Events;
namespace PepperDash.Essentials.Core
{
///
/// Represents a collection of individual route steps between a Source and a Destination device for a specific signal type.
///
public class RouteDescriptor
{
///
/// The destination device (sink or midpoint) for the route.
///
public IRoutingInputs Destination { get; private set; }
///
/// Gets or sets the InputPort
///
public RoutingInputPort InputPort { get; private set; }
///
/// Gets or sets the Source
///
public IRoutingOutputs Source { get; private set; }
///
/// Gets or sets the SignalType
///
public eRoutingSignalType SignalType { get; private set; }
///
/// Gets or sets the Routes
///
public List Routes { get; private set; }
///
/// Initializes a new instance of the class for a route without a specific destination input port.
///
/// The source device.
/// The destination device.
/// The type of signal being routed.
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType) : this(source, destination, null, signalType)
{
}
///
/// Initializes a new instance of the class for a route with a specific destination input port.
///
/// The source device.
/// The destination device.
/// The destination input port (optional).
/// The signal type for this route.
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, RoutingInputPort inputPort, eRoutingSignalType signalType)
{
Destination = destination;
InputPort = inputPort;
Source = source;
SignalType = signalType;
Routes = new List();
}
///
/// ExecuteRoutes method
///
public void ExecuteRoutes()
{
foreach (var route in Routes)
{
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString());
if (route.SwitchingDevice is IRoutingSinkWithSwitching sink)
{
sink.ExecuteSwitch(route.InputPort.Selector);
continue;
}
if (route.SwitchingDevice is IRouting switchingDevice)
{
switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType);
route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType);
Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
}
}
}
///
/// Releases the usage tracking for the route and optionally clears the route on the switching devices.
///
/// If true, attempts to clear the route on the switching devices (e.g., set input to null/0).
///
/// ReleaseRoutes method
///
public void ReleaseRoutes(bool clearRoute = false)
{
foreach (var route in Routes.Where(r => r.SwitchingDevice is IRouting))
{
if (route.SwitchingDevice is IRouting switchingDevice)
{
if(clearRoute)
{
try
{
switchingDevice.ExecuteSwitch(null, route.OutputPort.Selector, SignalType);
}
catch (Exception e)
{
Debug.LogError("Error executing switch: {exception}", e.Message);
}
}
if (route.OutputPort == null)
{
continue;
}
if (route.OutputPort.InUseTracker != null)
{
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
}
else
{
Debug.LogMessage(LogEventLevel.Error, "InUseTracker is null for OutputPort {0}", null, route.OutputPort.Key);
}
}
}
}
///
/// Returns a string representation of the route descriptor, including source, destination, and individual route steps.
///
/// A string describing the route.
///
/// ToString method
///
public override string ToString()
{
var routesText = Routes.Select(r => r.ToString()).ToArray();
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
}
}
/*///
/// Represents an collection of individual route steps between Source and Destination
///
///
/// Represents a RouteDescriptor
///
public class RouteDescriptor
{
///
/// Gets or sets the Destination
///
public IRoutingInputs Destination { get; private set; }
///
/// Gets or sets the Source
///
public IRoutingOutputs Source { get; private set; }
///
/// Gets or sets the SignalType
///
public eRoutingSignalType SignalType { get; private set; }
public List> Routes { get; private set; }
public RouteDescriptor(IRoutingOutputs source, IRoutingInputs destination, eRoutingSignalType signalType)
{
Destination = destination;
Source = source;
SignalType = signalType;
Routes = new List>();
}
///
/// ExecuteRoutes method
///
public void ExecuteRoutes()
{
foreach (var route in Routes)
{
Debug.LogMessage(LogEventLevel.Verbose, "ExecuteRoutes: {0}", null, route.ToString());
if (route.SwitchingDevice is IRoutingSinkWithSwitching sink)
{
sink.ExecuteSwitch(route.InputPort.Selector);
continue;
}
if (route.SwitchingDevice is IRouting switchingDevice)
{
switchingDevice.ExecuteSwitch(route.InputPort.Selector, route.OutputPort.Selector, SignalType);
route.OutputPort.InUseTracker.AddUser(Destination, "destination-" + SignalType);
Debug.LogMessage(LogEventLevel.Verbose, "Output port {0} routing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
}
}
}
///
/// ReleaseRoutes method
///
public void ReleaseRoutes()
{
foreach (var route in Routes)
{
if (route.SwitchingDevice is IRouting)
{
// Pull the route from the port. Whatever is watching the output's in use tracker is
// responsible for responding appropriately.
route.OutputPort.InUseTracker.RemoveUser(Destination, "destination-" + SignalType);
Debug.LogMessage(LogEventLevel.Verbose, "Port {0} releasing. Count={1}", null, route.OutputPort.Key, route.OutputPort.InUseTracker.InUseCountFeedback.UShortValue);
}
}
}
///
/// ToString method
///
///
public override string ToString()
{
var routesText = Routes.Select(r => r.ToString()).ToArray();
return string.Format("Route table from {0} to {1}:\r{2}", Source.Key, Destination.Key, string.Join("\r", routesText));
}
}*/
}