namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus;

/// <summary>
///     Single mapping point from <see cref="ModbusDriverOptions"/> to the concrete
///     <see cref="IModbusTransport"/> its <see cref="ModbusDriverOptions.Transport"/> selects.
///     Consumed by both <see cref="ModbusDriver"/>'s default transport-factory closure and the
///     AdminUI Test-Connect probe, so the <see cref="ModbusTransportMode"/> switch lives in
///     exactly one place.
/// </summary>
public static class ModbusTransportFactory
{
    /// <summary>
    ///     Builds the transport <paramref name="options"/>.<see cref="ModbusDriverOptions.Transport"/>
    ///     selects, threading every shared connection setting (Host/Port/Timeout/AutoReconnect/
    ///     KeepAlive/IdleDisconnectTimeout/Reconnect) through to whichever concrete transport is built.
    /// </summary>
    /// <param name="options">Driver configuration options.</param>
    /// <returns>A <see cref="ModbusRtuOverTcpTransport"/> when <see cref="ModbusTransportMode.RtuOverTcp"/>
    /// is selected; a <see cref="ModbusTcpTransport"/> when <see cref="ModbusTransportMode.Tcp"/> is selected.</returns>
    /// <exception cref="ArgumentOutOfRangeException">
    /// <paramref name="options"/>.<see cref="ModbusDriverOptions.Transport"/> is not a recognized
    /// <see cref="ModbusTransportMode"/> member — fail loudly rather than silently falling back to TCP/MBAP.
    /// </exception>
    public static IModbusTransport Create(ModbusDriverOptions options)
    {
        ArgumentNullException.ThrowIfNull(options);
        return options.Transport switch
        {
            ModbusTransportMode.RtuOverTcp => new ModbusRtuOverTcpTransport(
                options.Host, options.Port, options.Timeout, options.AutoReconnect,
                keepAlive: options.KeepAlive,
                idleDisconnect: options.IdleDisconnectTimeout,
                reconnect: options.Reconnect),
            ModbusTransportMode.Tcp => new ModbusTcpTransport(
                options.Host, options.Port, options.Timeout, options.AutoReconnect,
                keepAlive: options.KeepAlive,
                idleDisconnect: options.IdleDisconnectTimeout,
                reconnect: options.Reconnect),
            _ => throw new ArgumentOutOfRangeException(
                nameof(options), options.Transport, "Unknown Modbus transport mode."),
        };
    }
}
