@namespace Lumeo
@implements IAsyncDisposable

<div id="@_elementId" class="@CssClass" @attributes="AdditionalAttributes">
    @ChildContent
</div>

@inject ComponentInteropService Interop

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public int OffsetTop { get; set; } = 0;
    [Parameter] public int? OffsetBottom { get; set; }
    [Parameter] public string? Target { get; set; }
    [Parameter] public EventCallback<bool> OnChange { get; set; }
    [Parameter] public string? Class { get; set; }
    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }

    private readonly string _elementId = $"affix-{Guid.NewGuid():N}";
    private bool _registered;
    private bool _isFixed;

    private string CssClass => Class ?? "";

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (!firstRender) return;
        if (_registered) return;
        try
        {
            await Interop.RegisterAffix(_elementId, OffsetTop, OffsetBottom, Target, async (isFixed) =>
            {
                if (_isFixed != isFixed)
                {
                    _isFixed = isFixed;
                    await OnChange.InvokeAsync(isFixed);
                    await InvokeAsync(StateHasChanged);
                }
            });
            _registered = true;
        }
        catch (JSDisconnectedException) { }
        catch (ObjectDisposedException) { }
    }

    public async ValueTask DisposeAsync()
    {
        if (_registered)
        {
            try { await Interop.UnregisterAffix(_elementId); } catch (JSDisconnectedException) { }
        }
    }
}
