namespace ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
///
/// The handful of OPC UA status codes the engine layer needs to spell, plus the Part 4 severity
/// classification helpers that replaced the retired OpcUaQuality 3-state enum (Gitea #519).
///
/// Why these are bare uint literals. Commons and Runtime deliberately do not
/// reference the OPC UA SDK — exists precisely so the Runtime
/// project can publish values without dragging in Opc.Ua.Server. That is the same layering
/// decision the driver assemblies make, and it carries the same single failure mode: nothing checks
/// the literal against the name. StatusCodeParityTests closes it by reflection, and it can
/// only see a named constant — so add codes here rather than writing a literal at a call
/// site, exactly as Gitea #497 concluded for the drivers.
///
/// Severity, not equality, is what callers should branch on. A status code's top two
/// bits carry its Part 4 severity (00 = Good, 01 = Uncertain, 10/11 = Bad); everything below is the
/// sub-code. Before #519 the engine collapsed every value onto a 3-state enum here and the node
/// manager re-expanded Bad to a bare 0x80000000, so no driver's sub-code ever reached
/// a client. The sub-code now rides through to the SDK verbatim, and any code that only needs the
/// bucket uses / / rather than
/// comparing against or .
///
public static class OpcUaStatus
{
/// The value is good. Part 4 severity 00; the whole code is zero.
public const uint Good = 0x00000000;
/// Generic uncertain. Prefer a specific Uncertain* sub-code where one applies.
public const uint Uncertain = 0x40000000;
/// Generic bad, carrying no diagnostic beyond the severity. This is the value the retired
/// 3-state projection produced for every bad status; a caller that has something more
/// specific should say so instead.
public const uint Bad = 0x80000000;
/// No value has been received from the device yet. Written at materialisation and on every
/// address-space reset, so a freshly-deployed or just-rebuilt node reads as "not yet polled" rather
/// than as a device fault.
public const uint BadWaitingForInitialData = 0x80320000;
/// Communication with the source has been lost. The driver-connectivity annotation for a
/// native alarm condition, and the sentinel several drivers map an explicit "unavailable" reading to.
public const uint BadNoCommunication = 0x80310000;
/// An internal failure produced no usable value — the virtual-tag path's code for a script
/// that threw or timed out.
public const uint BadInternalError = 0x80020000;
/// Part 4 severity bucket of : the top two bits.
/// The status code to classify.
/// 0 for Good, 1 for Uncertain, 2 or 3 for Bad.
public static uint Severity(uint statusCode) => statusCode >> 30;
/// True when is in the Good severity bucket.
/// The status code to classify.
/// when the value is usable.
public static bool IsGood(uint statusCode) => Severity(statusCode) == 0;
/// True when is in the Uncertain severity bucket.
/// The status code to classify.
/// when the value is questionable but present.
public static bool IsUncertain(uint statusCode) => Severity(statusCode) == 1;
/// True when is in the Bad severity bucket.
/// The status code to classify.
/// when the value must not be trusted.
public static bool IsBad(uint statusCode) => Severity(statusCode) >= 2;
}