General/ReadOnlyTagSet.cs
using Sandbox;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ExtendedBox.General;

[JsonConverter(typeof(ReadOnlyTagSetJsonConverter))]
public class ReadOnlyTagSet : IEnumerable<string>
{
    private readonly ITagSet _tagSet;

    public bool IsEmpty => !_tagSet.Any();

    public ReadOnlyTagSet(ITagSet tagSet)
    {
        _tagSet = tagSet;
    }

    public bool Has(string tag) => _tagSet.Has(tag);
    public bool HasAll(IEnumerable<string> tags) => _tagSet.HasAll(tags);
    public bool HasAll(ITagSet other) => _tagSet.HasAll(other);
    public bool HasAll(params string[] tags) => _tagSet.HasAll(tags);
    public bool HasAny(IEnumerable<string> tags) => _tagSet.HasAny(tags);
    public bool HasAny(ITagSet other) => _tagSet.HasAny(other);
    public bool HasAny(params string[] tags) => _tagSet.HasAny(tags);

    public IEnumerable<string> TryGetAll() => this;
    public IEnumerator<string> GetEnumerator() => _tagSet.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();


    public static implicit operator ReadOnlyTagSet(ITagSet tagSet) => new(tagSet);
    public static implicit operator string[](ReadOnlyTagSet tagSet) => [.. tagSet];


    public class ReadOnlyTagSetJsonConverter : JsonConverter<ReadOnlyTagSet>
    {
        public const string Separator = ",";

        public override ReadOnlyTagSet? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if(reader.TokenType == JsonTokenType.String)
            {
                var str = reader.GetString()!;
                str = str.Replace(" ", string.Empty);
                var tags = str.Split(Separator);
                return TagSetBuilder.Create(tags).Build().ToReadOnly();
            }

            Log.Warning($"{GetType().Name} - unable to read from {reader.TokenType}");
            return default!;
        }

        public override void Write(Utf8JsonWriter writer, ReadOnlyTagSet value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(string.Join(Separator, value));
        }
    }
}

public static class TagSetExtensions
{
    public static ReadOnlyTagSet ToReadOnly(this ITagSet tagSet) => new(tagSet);
}