using System.Collections.Frozen;
using ZB.MOM.WW.HistorianGateway.Contracts.Grpc;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;
///
/// Maps the driver-agnostic (OPC UA Part 13 aggregate) onto the
/// gateway's native .
///
///
///
/// Served: → ,
/// Minimum → , Maximum → ,
/// Total → .
///
///
/// Deliberately NOT served (#679): (OPC UA Average is the arithmetic mean;
/// AVEVA's modes include no arithmetic mean — only the time-weighted one, which is TimeAverage) and
/// (AVEVA Counter is a rollover-counter increase, not a sample count).
/// Both surface as BadAggregateNotSupported rather than returning a different statistic under the requested name.
///
///
internal static class AggregateModeMapper
{
///
/// The aggregates the gateway serves — every defined member maps, derived from it so the
/// advertised set and the dispatch can never disagree.
/// returns it (#682); it is the ONLY declaration of the gateway's served set.
///
public static readonly IReadOnlySet Served =
Enum.GetValues().Where(a => TryMap(a) is not null).ToFrozenSet();
/// Maps an aggregate function to the gateway retrieval mode.
/// The driver-agnostic aggregate function.
/// The matching gateway .
/// A defined member the gateway has no retrieval mode for.
/// An undefined enum value.
public static RetrievalMode ToRetrievalMode(HistoryAggregateType aggregate)
{
if (TryMap(aggregate) is { } mode) return mode;
// Part 13 aggregates the gateway has no retrieval mode for (#285) — an UNDEFINED enum value is a
// programming error, but a defined-yet-unserved member is a normal client request the server
// answers with BadAggregateNotSupported.
if (Enum.IsDefined(aggregate)) throw new HistoryAggregateNotSupportedException(aggregate);
throw new ArgumentOutOfRangeException(
nameof(aggregate), aggregate, "Unmapped HistoryAggregateType — add a RetrievalMode mapping.");
}
/// The single mapping table: the retrieval mode for a served aggregate, or null.
private static RetrievalMode? TryMap(HistoryAggregateType aggregate) => aggregate switch
{
HistoryAggregateType.TimeAverage => RetrievalMode.TimeWeightedAverage,
HistoryAggregateType.Minimum => RetrievalMode.MinimumWithTime,
HistoryAggregateType.Maximum => RetrievalMode.MaximumWithTime,
HistoryAggregateType.Total => RetrievalMode.Integral,
_ => null,
};
}