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

/// <summary>
///     Wire-layer abstraction over a single PCCC tag. Mirrors <c>IAbCipTagRuntime</c>'s shape so
///     the same test-fake pattern applies; the only meaningful difference is the protocol layer
///     underneath (<c>ab_pccc</c> vs <c>ab_eip</c>).
/// </summary>
public interface IAbLegacyTagRuntime : IDisposable
{
    /// <summary>Initializes the tag runtime.</summary>
    /// <param name="cancellationToken">Cancellation token for the operation.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task InitializeAsync(CancellationToken cancellationToken);

    /// <summary>Reads the current value of the tag.</summary>
    /// <param name="cancellationToken">Cancellation token for the operation.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task ReadAsync(CancellationToken cancellationToken);

    /// <summary>Writes the encoded value to the tag.</summary>
    /// <param name="cancellationToken">Cancellation token for the operation.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task WriteAsync(CancellationToken cancellationToken);

    /// <summary>Gets the current status of the tag operation.</summary>
    /// <returns>The PCCC/libplctag status code of the last operation.</returns>
    int GetStatus();

    /// <summary>Decodes the tag value according to the specified data type.</summary>
    /// <param name="type">The data type to decode.</param>
    /// <param name="bitIndex">Optional bit index for bit-level access.</param>
    /// <returns>The decoded scalar value, boxed as <see cref="object"/>.</returns>
    object? DecodeValue(AbLegacyDataType type, int? bitIndex);

    /// <summary>
    ///     Decodes <paramref name="count"/> consecutive elements of a multi-element PCCC file
    ///     read as a typed CLR array (<c>short[]</c> for Int/AnalogInt, <c>int[]</c> for Long,
    ///     <c>float[]</c> for Float, <c>bool[]</c> for Bit), boxed as <see cref="object"/>. The
    ///     runtime must have been created with a matching element count (see
    ///     <see cref="AbLegacyTagCreateParams.ElementCount"/>) so the underlying buffer holds all
    ///     <paramref name="count"/> elements.
    /// </summary>
    /// <param name="type">The PCCC element data type.</param>
    /// <param name="count">The number of elements to decode.</param>
    /// <returns>The decoded elements as a typed CLR array, boxed as <see cref="object"/>.</returns>
    object? DecodeArray(AbLegacyDataType type, int count);

    /// <summary>Encodes a value for writing to the tag.</summary>
    /// <param name="type">The data type to encode.</param>
    /// <param name="bitIndex">Optional bit index for bit-level access.</param>
    /// <param name="value">The value to encode.</param>
    void EncodeValue(AbLegacyDataType type, int? bitIndex, object? value);
}

public interface IAbLegacyTagFactory
{
    /// <summary>Creates a tag runtime instance with the specified parameters.</summary>
    /// <param name="createParams">The tag creation parameters.</param>
    /// <returns>The created tag runtime instance.</returns>
    IAbLegacyTagRuntime Create(AbLegacyTagCreateParams createParams);
}

/// <param name="Gateway">The PLC gateway host (IP or DNS).</param>
/// <param name="Port">The EtherNet/IP TCP port.</param>
/// <param name="CipPath">The CIP routing path to the PLC (e.g. <c>1,0</c>).</param>
/// <param name="LibplctagPlcAttribute">The libplctag <c>plc</c> attribute (e.g. <c>slc500</c>).</param>
/// <param name="TagName">The PCCC file address passed to libplctag's <c>name</c> attribute.</param>
/// <param name="Timeout">The read/write operation timeout.</param>
/// <param name="ElementCount">
///     libplctag element count for the tag. <c>1</c> (the default) reads a single PCCC file
///     element (scalar). A value &gt; 1 reads that many consecutive elements from the base
///     address (e.g. <c>N7:0</c> with an element count of 5 reads <c>N7:0</c>..<c>N7:4</c>),
///     which the runtime surfaces via <see cref="IAbLegacyTagRuntime.DecodeArray"/>.
/// </param>
public sealed record AbLegacyTagCreateParams(
    string Gateway,
    int Port,
    string CipPath,
    string LibplctagPlcAttribute,
    string TagName,
    TimeSpan Timeout,
    int ElementCount = 1);
