using Serilog;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Core.Scripting;
///
/// The API user scripts see as the global ctx. Abstract — concrete subclasses
/// (e.g. VirtualTagScriptContext, AlarmScriptContext) plug in the
/// actual tag-backend + logger + virtual-tag writer for each evaluation. Phase 7 plan
/// decision #6: scripts can read any tag, write only to virtual tags, and have no
/// other .NET reach — no HttpClient, no File, no Process, no reflection.
///
///
///
/// Every member on this type MUST be serializable in the narrow sense that
/// can recognize tag-access call sites from the
/// script AST. Method names used from scripts are locked — renaming
/// or is a breaking change for every
/// authored script and the dependency extractor must update in lockstep.
///
///
/// New helpers (, ) are additive: adding a
/// method doesn't invalidate existing scripts. Do not remove or rename without a
/// plan-level decision + migration for authored scripts.
///
///
public abstract class ScriptContext
{
///
/// Read a tag's current value + quality + source timestamp. Path syntax is
/// Enterprise/Site/Area/Line/Equipment/TagName (forward-slash delimited,
/// matching the Equipment-namespace browse tree). Returns a
/// so scripts branch on quality without a second
/// call.
///
///
/// MUST be a string literal in the script source — dynamic
/// paths (variables, concatenation, method-returned strings) are rejected at
/// publish by . This is intentional: the static
/// dependency set is required for the change-driven scheduler to subscribe to the
/// right upstream tags at load time.
///
public abstract DataValueSnapshot GetTag(string path);
///
/// Write a value to a virtual tag. Operator scripts cannot write to driver-sourced
/// tags — the OPC UA dispatch in DriverNodeManager rejects that separately
/// per ADR-002 with BadUserAccessDenied. This method is the only write path
/// virtual tags have.
///
///
/// Path rules identical to — literal only, dependency
/// extractor tracks the write targets so the engine knows what downstream
/// subscribers to notify.
///
public abstract void SetVirtualTag(string path, object? value);
///
/// Current UTC timestamp. Prefer this over in
/// scripts so the harness can supply a deterministic clock for tests.
///
public abstract DateTime Now { get; }
///
/// Per-script Serilog logger. Output lands in the dedicated scripts-*.log
/// sink with structured property ScriptName = the script's configured name.
/// Use at error level to surface problems; main opcua-*.log receives a
/// companion WARN entry so operators see script errors in the primary log.
///
public abstract ILogger Logger { get; }
///
/// Deadband helper — returns true when differs
/// from by more than .
/// Useful for alarm predicates that shouldn't flicker on small noise. Pure
/// function; no side effects.
///
public static bool Deadband(double current, double previous, double tolerance)
=> Math.Abs(current - previous) > tolerance;
}