namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.PlcFamilies;

/// <summary>
///     Per-family libplctag defaults. Picked up at device-initialization time so each PLC
///     family gets the correct ConnectionSize, path semantics, and quirks applied without
///     the caller having to know the protocol-level differences.
/// </summary>
/// <remarks>
///     Mirrors the shape of the Modbus driver's per-family profiles (DL205, Siemens S7,
///     Mitsubishi MELSEC). ControlLogix is the baseline; each subsequent family is a delta.
///     Family-specific behaviour (ControlLogix / CompactLogix / Micro800 / GuardLogix) is
///     covered by the unit tests in <c>AbCipPlcFamilyTests</c>.
/// </remarks>
public sealed record AbCipPlcFamilyProfile(
    string LibplctagPlcAttribute,
    int DefaultConnectionSize,
    string DefaultCipPath,
    bool SupportsRequestPacking,
    bool SupportsConnectedMessaging,
    int MaxFragmentBytes)
{
    /// <summary>Look up the profile for a configured family.</summary>
    /// <param name="family">The PLC family to look up the profile for.</param>
    /// <returns>The matching profile, or <see cref="ControlLogix"/> if the family is unrecognized.</returns>
    public static AbCipPlcFamilyProfile ForFamily(AbCipPlcFamily family) => family switch
    {
        AbCipPlcFamily.ControlLogix => ControlLogix,
        AbCipPlcFamily.CompactLogix => CompactLogix,
        AbCipPlcFamily.Micro800 => Micro800,
        AbCipPlcFamily.GuardLogix => GuardLogix,
        _ => ControlLogix,
    };

    public static readonly AbCipPlcFamilyProfile ControlLogix = new(
        LibplctagPlcAttribute: "controllogix",
        DefaultConnectionSize: 4002, // Large Forward Open; FW20+
        DefaultCipPath: "1,0",
        SupportsRequestPacking: true,
        SupportsConnectedMessaging: true,
        MaxFragmentBytes: 4000);

    public static readonly AbCipPlcFamilyProfile CompactLogix = new(
        LibplctagPlcAttribute: "compactlogix",
        DefaultConnectionSize: 504, // 5069-L3x narrower buffer; safe baseline that never over-shoots
        DefaultCipPath: "1,0",
        SupportsRequestPacking: true,
        SupportsConnectedMessaging: true,
        MaxFragmentBytes: 500);

    public static readonly AbCipPlcFamilyProfile Micro800 = new(
        LibplctagPlcAttribute: "micro800",
        DefaultConnectionSize: 488, // Micro800 hard cap
        DefaultCipPath: "",         // no backplane routing
        SupportsRequestPacking: false,
        SupportsConnectedMessaging: false, // unconnected-only on most models
        MaxFragmentBytes: 484);

    public static readonly AbCipPlcFamilyProfile GuardLogix = new(
        LibplctagPlcAttribute: "controllogix", // wire protocol identical; safety partition is tag-level
        DefaultConnectionSize: 4002,
        DefaultCipPath: "1,0",
        SupportsRequestPacking: true,
        SupportsConnectedMessaging: true,
        MaxFragmentBytes: 4000);
}
