using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.DeviceForms;
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers;
///
/// DriverType → typed driver-config form component, rendered by DriverConfigModal through
/// <DynamicComponent>.
/// Why this is a map and not the @switch it replaced. A Razor @switch compiles
/// into BuildRenderTree's IL, so no test can enumerate its cases — which is exactly how the modal
/// came to be missing a Calculation arm while the sibling driver-picker guard stayed green
/// (deferment.md G-1/G-4). The picker test only works because RawDriverTypeDialog keeps its
/// data in a field the markup enumerates; this type gives the two config modals the same property, and
/// being public it needs none of that test's BindingFlags.NonPublic fragility.
/// Modelled on TagConfigEditorMap. Guarded by DriverFormMapParityTests.
///
public static class DriverConfigFormMap
{
private static readonly IReadOnlyDictionary Map =
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
[DriverTypeNames.Modbus] = typeof(ModbusDriverForm),
[DriverTypeNames.S7] = typeof(S7DriverForm),
[DriverTypeNames.AbCip] = typeof(AbCipDriverForm),
[DriverTypeNames.AbLegacy] = typeof(AbLegacyDriverForm),
[DriverTypeNames.TwinCAT] = typeof(TwinCATDriverForm),
[DriverTypeNames.FOCAS] = typeof(FocasDriverForm),
[DriverTypeNames.OpcUaClient] = typeof(OpcUaClientDriverForm),
[DriverTypeNames.Galaxy] = typeof(GalaxyDriverForm),
[DriverTypeNames.Sql] = typeof(SqlDriverForm),
[DriverTypeNames.Mqtt] = typeof(MqttDriverForm),
[DriverTypeNames.MTConnect] = typeof(MTConnectDriverForm),
[DriverTypeNames.Calculation] = typeof(CalculationDriverForm),
};
/// The driver types that have a typed config form.
public static IReadOnlyCollection MappedDriverTypes => (IReadOnlyCollection)Map.Keys;
/// Resolves the form component for a driver type, or null when none is mapped (the modal
/// then renders its "no typed config form" warning rather than crashing).
/// The driver type name.
/// The form component type, or .
public static Type? Resolve(string? driverType) =>
driverType is not null && Map.TryGetValue(driverType, out var t) ? t : null;
}
///
/// DriverType → typed device-config form component, rendered by DeviceModal.
/// Not every driver has one, by design. The types in
/// hold ONE connection per driver instance and author it on the
/// driver form, so a per-device endpoint editor would be meaningless. The parity test consults that set
/// rather than demanding total coverage — which keeps it a real guard instead of one that has to be
/// suppressed.
///
public static class DeviceFormMap
{
private static readonly IReadOnlyDictionary Map =
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
[DriverTypeNames.Modbus] = typeof(ModbusDeviceForm),
[DriverTypeNames.S7] = typeof(S7DeviceForm),
[DriverTypeNames.AbCip] = typeof(AbCipDeviceForm),
[DriverTypeNames.AbLegacy] = typeof(AbLegacyDeviceForm),
[DriverTypeNames.TwinCAT] = typeof(TwinCATDeviceForm),
[DriverTypeNames.FOCAS] = typeof(FocasDeviceForm),
[DriverTypeNames.OpcUaClient] = typeof(OpcUaClientDeviceForm),
[DriverTypeNames.Galaxy] = typeof(GalaxyDeviceForm),
[DriverTypeNames.Mqtt] = typeof(MqttDeviceForm),
};
///
/// Driver types that hold a single connection at the DRIVER level, so they legitimately have no
/// per-device form. Galaxy and Mqtt author a connection on the driver form and keep an informational
/// device form; Sql (one connection string), MTConnect (one Agent URI) and Calculation (no
/// connection at all) have no device form to render.
/// Read by DriverConfigModal so the operator is told where the endpoint actually lives —
/// it previously hardcoded Galaxy-or-Mqtt and told Sql/MTConnect authors to go and find an endpoint
/// field on the device that does not exist (deferment.md G-3).
///
public static readonly IReadOnlySet SingleConnectionDriverTypes =
new HashSet(StringComparer.OrdinalIgnoreCase)
{
DriverTypeNames.Galaxy,
DriverTypeNames.Mqtt,
DriverTypeNames.Sql,
DriverTypeNames.MTConnect,
DriverTypeNames.Calculation,
};
/// The driver types that have a typed device form.
public static IReadOnlyCollection MappedDriverTypes => (IReadOnlyCollection)Map.Keys;
/// Resolves the device form component for a driver type, or null when none is mapped.
/// The driver type name.
/// The form component type, or .
public static Type? Resolve(string? driverType) =>
driverType is not null && Map.TryGetValue(driverType, out var t) ? t : null;
/// True when this driver authors its connection on the DRIVER form rather than per-device.
/// The driver type name.
/// when the connection is driver-level.
public static bool IsSingleConnection(string? driverType) =>
driverType is not null && SingleConnectionDriverTypes.Contains(driverType);
}