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

/// <summary>
///     Filters system / infrastructure tags out of discovered tag sets. A Logix controller's
///     symbol table exposes user tags alongside module-config objects, routine pointers, task
///     pointers, and <c>__DEFVAL_*</c> stubs that are noise for the OPC UA address space.
/// </summary>
/// <remarks>
///     Lifted from the filter conventions documented in the Logix 5000 Controllers General
///     Instructions Reference. The list is conservative — when in doubt, a tag is surfaced
///     rather than hidden so operators can see it and the config flow can explicitly hide it
///     via UnsArea ACL.
/// </remarks>
public static class AbCipSystemTagFilter
{
    /// <summary>
    ///     <c>true</c> when the tag name matches a well-known system-tag pattern the driver
    ///     should hide from the default address space. Case-sensitive — Logix symbols are
    ///     always preserved case and the system-tag prefixes are uppercase by convention.
    /// </summary>
    /// <param name="tagName">The tag name to check.</param>
    /// <returns><c>true</c> when the tag name matches a known system-tag pattern; otherwise <c>false</c>.</returns>
    public static bool IsSystemTag(string tagName)
    {
        if (string.IsNullOrWhiteSpace(tagName)) return true;

        // Internal backing store for tag defaults — never user-meaningful.
        if (tagName.StartsWith("__DEFVAL_", StringComparison.Ordinal)) return true;
        if (tagName.StartsWith("__DEFAULT_", StringComparison.Ordinal)) return true;

        // Routine and Task pointer pseudo-tags.
        if (tagName.StartsWith("Routine:", StringComparison.Ordinal)) return true;
        if (tagName.StartsWith("Task:", StringComparison.Ordinal)) return true;

        // Logix module-config auto-generated names — Local:1:I, Local:1:O, etc. Module data is
        // exposed separately via the dedicated hardware mapping; the auto-generated symbol-table
        // entries duplicate that.
        if (tagName.StartsWith("Local:", StringComparison.Ordinal) && tagName.Contains(':')) return true;

        // Map / Mapped IO alias tags (MainProgram.MapName pattern — dot-separated but prefixed
        // with a reserved colon-carrying prefix to avoid false positives on user member access).
        if (tagName.StartsWith("Map:", StringComparison.Ordinal)) return true;

        // Axis / Cam / Motion-Group predefined structures — exposed separately through motion API.
        if (tagName.StartsWith("Axis:", StringComparison.Ordinal)) return true;
        if (tagName.StartsWith("Cam:", StringComparison.Ordinal)) return true;
        if (tagName.StartsWith("MotionGroup:", StringComparison.Ordinal)) return true;

        return false;
    }
}
