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

/// <summary>
///     Per-family libplctag defaults for PCCC PLCs. SLC 500 / MicroLogix / PLC-5 / LogixPccc
///     (Logix controller accessed via the PLC-5 compatibility layer — rare but real).
/// </summary>
public sealed record AbLegacyPlcFamilyProfile(
    string LibplctagPlcAttribute,
    string DefaultCipPath,
    /// <summary>
    ///     Reserved for future array-length clamping.  <b>Not currently enforced anywhere in the
    ///     driver.</b>  The values are approximate upper bounds derived from PCCC packet payload
    ///     limits (e.g. SLC 5/05 240 bytes is the PCCC-over-EIP data cap, not a libplctag fragment
    ///     limit).  Do not rely on this field for sizing decisions until an enforcement point is added.
    /// </summary>
    int MaxTagBytes,
    bool SupportsStringFile,
    bool SupportsLongFile)
{
    /// <summary>Gets the profile for the specified PLC family.</summary>
    /// <param name="family">The PLC family.</param>
    /// <remarks>
    ///     Any unrecognised <paramref name="family"/> value (e.g. an integer cast to the enum, or a
    ///     value added to <see cref="AbLegacyPlcFamily"/> before this switch is updated) silently
    ///     returns the <see cref="Slc500"/> profile.  This is intentional: it preserves
    ///     forward-compatibility for device configs authored against a build that predates a new
    ///     family enum member, preferring a safe default over a startup exception.
    /// </remarks>
    /// <returns>The libplctag profile defaults for <paramref name="family"/>.</returns>
    public static AbLegacyPlcFamilyProfile ForFamily(AbLegacyPlcFamily family) => family switch
    {
        AbLegacyPlcFamily.Slc500 => Slc500,
        AbLegacyPlcFamily.MicroLogix => MicroLogix,
        AbLegacyPlcFamily.Plc5 => Plc5,
        AbLegacyPlcFamily.LogixPccc => LogixPccc,
        _ => Slc500,
    };

    public static readonly AbLegacyPlcFamilyProfile Slc500 = new(
        LibplctagPlcAttribute: "slc500",
        DefaultCipPath: "1,0",
        MaxTagBytes: 240,           // SLC 5/05 PCCC max packet data
        SupportsStringFile: true,   // ST file available SLC 5/04+
        SupportsLongFile: true);    // L file available SLC 5/05+

    public static readonly AbLegacyPlcFamilyProfile MicroLogix = new(
        LibplctagPlcAttribute: "micrologix",
        DefaultCipPath: "",         // MicroLogix 1100/1400 use direct EIP, no backplane path
        MaxTagBytes: 232,
        SupportsStringFile: true,
        SupportsLongFile: false);   // ML 1100/1200/1400 don't ship L files

    public static readonly AbLegacyPlcFamilyProfile Plc5 = new(
        LibplctagPlcAttribute: "plc5",
        DefaultCipPath: "1,0",
        MaxTagBytes: 240,           // DF1 full-duplex packet limit at 264 bytes, PCCC-over-EIP caps lower
        SupportsStringFile: true,
        SupportsLongFile: false);   // PLC-5 predates L files

    /// <summary>
    ///     Logix ControlLogix / CompactLogix accessed through the legacy PCCC compatibility layer.
    ///     Rare but real — some legacy HMI integrations address Logix controllers as if they were
    ///     PLC-5 via the PCCC-passthrough mechanism.
    /// </summary>
    public static readonly AbLegacyPlcFamilyProfile LogixPccc = new(
        LibplctagPlcAttribute: "logixpccc",
        DefaultCipPath: "1,0",
        MaxTagBytes: 240,
        SupportsStringFile: true,
        SupportsLongFile: true);
}

/// <summary>Which PCCC PLC family the device is.</summary>
public enum AbLegacyPlcFamily
{
    Slc500,
    MicroLogix,
    Plc5,
    LogixPccc,
}
