using ZB.MOM.WW.OtOpcUa.Core.Abstractions;

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

/// <summary>
///     TwinCAT / IEC 61131-3 atomic data types. Wider type surface than Logix because IEC adds
///     <c>WSTRING</c> (UTF-16) and <c>TIME</c>/<c>DATE</c>/<c>DT</c>/<c>TOD</c> variants.
/// </summary>
public enum TwinCATDataType
{
    Bool,
    SInt,   // signed 8-bit
    USInt,  // unsigned 8-bit
    Int,    // signed 16-bit
    UInt,   // unsigned 16-bit
    DInt,   // signed 32-bit
    UDInt,  // unsigned 32-bit
    LInt,   // signed 64-bit
    ULInt,  // unsigned 64-bit
    Real,   // 32-bit IEEE-754
    LReal,  // 64-bit IEEE-754
    String, // ASCII string
    WString,// UTF-16 string
    Time,   // TIME — ms since epoch of day, stored as UDINT
    Date,   // DATE — days since 1970-01-01, stored as UDINT
    DateTime, // DT — seconds since 1970-01-01, stored as UDINT
    TimeOfDay,// TOD — ms since midnight, stored as UDINT
    /// <summary>UDT / FB instance. Resolved per member at discovery time.</summary>
    Structure,
}

public static class TwinCATDataTypeExtensions
{
    public static DriverDataType ToDriverDataType(this TwinCATDataType t) => t switch
    {
        TwinCATDataType.Bool => DriverDataType.Boolean,
        TwinCATDataType.SInt or TwinCATDataType.USInt
            or TwinCATDataType.Int or TwinCATDataType.UInt
            or TwinCATDataType.DInt or TwinCATDataType.UDInt => DriverDataType.Int32,
        TwinCATDataType.LInt or TwinCATDataType.ULInt => DriverDataType.Int32, // matches Int64 gap
        TwinCATDataType.Real => DriverDataType.Float32,
        TwinCATDataType.LReal => DriverDataType.Float64,
        TwinCATDataType.String or TwinCATDataType.WString => DriverDataType.String,
        TwinCATDataType.Time or TwinCATDataType.Date
            or TwinCATDataType.DateTime or TwinCATDataType.TimeOfDay => DriverDataType.Int32,
        TwinCATDataType.Structure => DriverDataType.String,
        _ => DriverDataType.Int32,
    };
}
