using System;

namespace AyCode.Core.Serializers.Attributes;

/// <summary>
/// Marks a class or struct for Source Generator based binary serialization.
/// When applied, the Source Generator will create optimized serialize/deserialize methods
/// at compile time, eliminating the need for runtime reflection or compiled expressions.
/// </summary>
/// <remarks>
/// If this attribute is not present, the serializer falls back to the existing
/// compiled expression based approach which works for all types.
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
public sealed class AcBinarySerializableAttribute : Attribute
{
    public bool EnableMetadataFeature { get; }
    public bool EnableIdTrackingFeature { get; }
    public bool EnableRefHandlingFeature { get; }
    public bool EnableInternStringFeature { get; }

    /// <summary>
    /// When <c>true</c> (default): the SGen-emitted writer/scan code includes the per-property
    /// <c>HasPropertyFilter</c> branch + filter-context allocation + lambda-call. Required for runtime
    /// <see cref="AyCode.Core.Serializers.Binaries.BinaryPropertyFilter"/> to take effect on this type.
    /// <para>When <c>false</c>: the SGen-emitted writer/scan code <b>omits</b> the filter check entirely
    /// for every property of this type — leaner generated code on the hot path. Use this when the
    /// type is never serialized with a property-filter (typical for high-throughput message types).
    /// Filter callbacks set on <c>AcBinarySerializerOptions.PropertyFilter</c> will be silently ignored
    /// for this type's properties — only set <c>false</c> if you can guarantee no consumer relies on
    /// per-property filtering for this specific type.</para>
    /// </summary>
    public bool EnablePropertyFilterFeature { get; }

    public AcBinarySerializableAttribute() : this(true)
    {
    }

    public AcBinarySerializableAttribute(bool enableAllFeatures)
    {
        EnableMetadataFeature = enableAllFeatures;
        EnableIdTrackingFeature = enableAllFeatures;
        EnableRefHandlingFeature = enableAllFeatures;
        EnableInternStringFeature = enableAllFeatures;
        EnablePropertyFilterFeature = enableAllFeatures;
    }

    public AcBinarySerializableAttribute(bool enableMetadataFeature, bool enableIdTrackingFeature, bool enableRefHandlingFeature, bool enableInternStringFeature, bool enablePropertyFilterFeature)
    {
        EnableMetadataFeature = enableMetadataFeature;
        EnableIdTrackingFeature = enableIdTrackingFeature;
        EnableRefHandlingFeature = enableRefHandlingFeature;
        EnableInternStringFeature = enableInternStringFeature;
        EnablePropertyFilterFeature = enablePropertyFilterFeature;
    }
}
