using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;

namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;

/// <summary>
///     Production <see cref="IOpcUaAddressSpaceSink"/> binding for v2 — bridges
///     OpcUaPublishActor's writes to the SDK address space owned by
///     <see cref="OtOpcUaNodeManager"/>. The host wires this in once the StandardServer has
///     been started (so the node manager exists).
/// </summary>
public sealed class SdkAddressSpaceSink : IOpcUaAddressSpaceSink, ISurgicalAddressSpaceSink
{
    private readonly OtOpcUaNodeManager _nodeManager;

    /// <summary>Initializes a new instance of the SdkAddressSpaceSink class.</summary>
    /// <param name="nodeManager">The OPC UA node manager.</param>
    public SdkAddressSpaceSink(OtOpcUaNodeManager nodeManager)
    {
        ArgumentNullException.ThrowIfNull(nodeManager);
        _nodeManager = nodeManager;
    }

    /// <inheritdoc />
    public void WriteValue(string nodeId, object? value, OpcUaQuality quality, DateTime sourceTimestampUtc, AddressSpaceRealm realm)
        => _nodeManager.WriteValue(nodeId, value, quality, sourceTimestampUtc, realm);

    /// <inheritdoc />
    public void WriteAlarmCondition(string alarmNodeId, AlarmConditionSnapshot state, DateTime sourceTimestampUtc, AddressSpaceRealm realm)
        => _nodeManager.WriteAlarmCondition(alarmNodeId, state, sourceTimestampUtc, realm);

    public void WriteAlarmQuality(string alarmNodeId, OpcUaQuality quality, DateTime sourceTimestampUtc, AddressSpaceRealm realm)
        => _nodeManager.WriteAlarmQuality(alarmNodeId, quality, sourceTimestampUtc, realm);

    /// <inheritdoc />
    public void MaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity, AddressSpaceRealm realm, bool isNative = false)
        => _nodeManager.MaterialiseAlarmCondition(alarmNodeId, equipmentNodeId, displayName, alarmType, severity, realm, isNative);

    /// <inheritdoc />
    public void WireAlarmNotifiers(string alarmNodeId, AddressSpaceRealm alarmRealm, IReadOnlyList<string> notifierFolderNodeIds, AddressSpaceRealm notifierFolderRealm)
        => _nodeManager.WireAlarmNotifiers(alarmNodeId, alarmRealm, notifierFolderNodeIds, notifierFolderRealm);

    /// <inheritdoc />
    public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName, AddressSpaceRealm realm)
        => _nodeManager.EnsureFolder(folderNodeId, parentNodeId, displayName, realm);

    /// <inheritdoc />
    public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType, bool writable, AddressSpaceRealm realm, string? historianTagname = null, bool isArray = false, uint? arrayLength = null)
        => _nodeManager.EnsureVariable(variableNodeId, parentFolderNodeId, displayName, dataType, writable, realm, historianTagname, isArray, arrayLength);

    /// <inheritdoc />
    public bool UpdateTagAttributes(string variableNodeId, bool writable, string? historianTagname, string dataType, bool isArray, uint? arrayLength, AddressSpaceRealm realm)
        => _nodeManager.UpdateTagAttributes(variableNodeId, writable, historianTagname, dataType, isArray, arrayLength, realm);

    /// <inheritdoc />
    public bool UpdateFolderDisplayName(string folderNodeId, string displayName, AddressSpaceRealm realm)
        => _nodeManager.UpdateFolderDisplayName(folderNodeId, displayName, realm);

    /// <inheritdoc />
    public bool RemoveVariableNode(string variableNodeId, AddressSpaceRealm realm)
        => _nodeManager.RemoveVariableNode(variableNodeId, realm);

    /// <inheritdoc />
    public bool RemoveAlarmConditionNode(string alarmNodeId, AddressSpaceRealm realm)
        => _nodeManager.RemoveAlarmConditionNode(alarmNodeId, realm);

    /// <inheritdoc />
    public bool RemoveEquipmentSubtree(string equipmentNodeId, AddressSpaceRealm realm)
        => _nodeManager.RemoveEquipmentSubtree(equipmentNodeId, realm);

    /// <inheritdoc />
    public void RebuildAddressSpace() => _nodeManager.RebuildAddressSpace();

    /// <inheritdoc />
    public void RaiseNodesAddedModelChange(string affectedNodeId, AddressSpaceRealm realm) => _nodeManager.RaiseNodesAddedModelChange(affectedNodeId, realm);

    /// <inheritdoc />
    public void AddReference(string sourceNodeId, AddressSpaceRealm sourceRealm, string targetNodeId, AddressSpaceRealm targetRealm, string referenceType = "Organizes")
        => _nodeManager.AddReference(sourceNodeId, sourceRealm, targetNodeId, targetRealm, referenceType);
}
