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

/// <summary>
///     The set of value types a Modbus tag can decode to. Each type implies a fixed
///     register-count: <see cref="Bool"/> / <see cref="Int16"/> / <see cref="UInt16"/> /
///     <see cref="BitInRegister"/> / <see cref="Bcd16"/> = 1 register; <see cref="Int32"/> /
///     <see cref="UInt32"/> / <see cref="Float32"/> / <see cref="Bcd32"/> = 2 registers;
///     <see cref="Int64"/> / <see cref="UInt64"/> / <see cref="Float64"/> = 4 registers;
///     <see cref="String"/> = ceil(StringLength / 2) registers.
/// </summary>
/// <remarks>
///     Lives in the shared addressing assembly (alongside <see cref="ModbusRegion"/>) so the
///     Admin UI and the parser can speak about value types without taking a transport-layer
///     dependency on the wire driver.
/// </remarks>
public enum ModbusDataType
{
    Bool,
    Int16,
    UInt16,
    Int32,
    UInt32,
    Int64,
    UInt64,
    Float32,
    Float64,
    /// <summary>Single bit within a holding register. <c>BitIndex</c> selects 0-15 LSB-first.</summary>
    BitInRegister,
    /// <summary>ASCII string packed 2 chars per register, <c>StringLength</c> characters long.</summary>
    String,
    /// <summary>
    ///     16-bit binary-coded decimal. Each nibble encodes one decimal digit (0-9). Register
    ///     value <c>0x1234</c> decodes as decimal <c>1234</c> — NOT binary <c>0x04D2 = 4660</c>.
    ///     DL205/DL260 and several Mitsubishi / Omron families store timers, counters, and
    ///     operator-facing numerics as BCD by default.
    /// </summary>
    Bcd16,
    /// <summary>
    ///     32-bit (two-register) BCD. Decodes 8 decimal digits. Word ordering follows the tag's
    ///     <see cref="ModbusByteOrder"/> the same way <see cref="Int32"/> does.
    /// </summary>
    Bcd32,
}

/// <summary>
///     Word/byte ordering for multi-register types. The four-letter mnemonic refers to the
///     order in which bytes A, B, C, D appear on the wire when decoding a 4-byte value (e.g.
///     a Float32) from two consecutive 16-bit registers.
/// </summary>
/// <remarks>
///     <para>
///         <see cref="BigEndian"/> (<c>ABCD</c>) is the Modbus-spec default: high word at lower
///         address, big-endian within each register.
///     </para>
///     <para>
///         <see cref="WordSwap"/> (<c>CDAB</c>): keeps bytes big-endian within each register
///         but swaps the word pair. Common on Siemens S7 over Modbus, Allen-Bradley, several
///         Modicon families.
///     </para>
///     <para>
///         <see cref="ByteSwap"/> (<c>BADC</c>): keeps the word pair in spec order but swaps
///         bytes within each register. Encountered on a handful of legacy controllers exposing
///         little-endian internals through Modbus.
///     </para>
///     <para>
///         <see cref="FullReverse"/> (<c>DCBA</c>): full byte reversal — equivalent to reading
///         the value as little-endian. Some industrial PCs and gateways that bridge CAN /
///         EtherNet/IP into Modbus surface their backplane order this way.
///     </para>
///     <para>
///         For 8-byte (Int64 / UInt64 / Float64) values the same A/B/C/D semantics apply
///         pairwise across the four registers; the implementation is straight-line.
///     </para>
/// </remarks>
public enum ModbusByteOrder
{
    BigEndian,
    WordSwap,
    ByteSwap,
    FullReverse,
}

/// <summary>
///     Per-register byte order for ASCII strings packed 2 chars per register. Standard Modbus
///     convention is <see cref="HighByteFirst"/> — the first character of each pair occupies
///     the high byte of the register. AutomationDirect DirectLOGIC (DL205, DL260, DL350) and a
///     handful of legacy controllers pack <see cref="LowByteFirst"/>, which inverts that within
///     each register. Word ordering across multiple registers is always ascending address for
///     strings — only the byte order inside each register flips.
/// </summary>
/// <remarks>
///     <para>
///         <b>Grammar scope:</b> this enum is intentionally NOT
///         expressible through the <see cref="ModbusAddressParser"/> grammar string. The grammar
///         has no token form for it, and <see cref="ParsedModbusAddress"/> has no field for it —
///         a DL205 string tag parsed from the grammar always carries the driver's default order.
///     </para>
///     <para>
///         The string byte order is configurable only via the structured tag definition (the
///         driver's <c>ModbusTagDefinition.StringByteOrder</c> field). Adding a grammar token
///         was explicitly considered and rejected: the 3rd-field slot is the multi-register
///         word/byte order (ABCD/CDAB/BADC/DCBA) and the 4th-field slot is the array count, so
///         a fifth <c>:&lt;order&gt;</c> suffix would conflict with the count-shape disambiguation.
///         Sites that need per-tag low-byte-first strings must use the structured form. The
///         default high-byte-first matches the Modbus spec and Ignition / Kepware default
///         behaviour.
///     </para>
///     <para>See <c>docs/v2/dl205.md</c> §Strings for the DL205-specific rationale.</para>
/// </remarks>
public enum ModbusStringByteOrder
{
    HighByteFirst,
    LowByteFirst,
}
