@inject IJSRuntime JSRuntime
@implements IDisposable

<polygon @ref="Ref" class="@(IsSetting ? "setting" : "")" fill="@Model.Fill" @ondblclick="OnDoubleClick" style="visibility: @(IsShow ? "visible" : "hidden")" />

@code {
    [Parameter, EditorRequired]
    public ZoneModel Model { get; set; } = null!;

    [Parameter]
    public EventCallback<ZoneModel> DoubleClick { get; set; }

    [Parameter]
    public bool IsSetting { get; set; }

    [Parameter]
    public bool IsShow { get; set; }

    [CascadingParameter]
    protected bool MapIsActive { get; set; }

    private ElementReference Ref;
    private DotNetObjectReference<Zone> DotNetObj = null!;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (!firstRender) return;

        DotNetObj = DotNetObjectReference.Create(this);
        await JSRuntime.InvokeVoidAsync("AddEventListener", DotNetObj, Ref, "click", nameof(Click), false);
        await UpdateData();
    }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        bool UpdateZone = false;
        if (parameters.TryGetValue(nameof(Model), out ZoneModel? model))
        {
            if (((Model?.Id ?? Guid.Empty) != (model?.Id ?? Guid.Empty)))
            {
                if (Model != null)
                {
                    Model.ControlNodePosittionChanged -= UpdateData;
                    Model.TypeChanged -= StateHasChanged;
                    Model.ActiveChanged -= ActiveChanged;
                }

                if (model != null)
                {
                    model.ControlNodePosittionChanged += UpdateData;
                    model.TypeChanged += StateHasChanged;
                    model.ActiveChanged += ActiveChanged;

                    UpdateZone = true;
                }
            }
        }

        await base.SetParametersAsync(parameters);
        if (UpdateZone) await UpdateData();
    }

    private async Task OnDoubleClick()
    {
        await DoubleClick.InvokeAsync(Model);
    }

    [JSInvokable]
    public void Click()
    {
        Model.Active();
    }

    private async void ActiveChanged(ZoneModel zone, bool state) => await JSRuntime.InvokeVoidAsync(state ? "AddSelected" : "RemoveSelected", Ref);

    private async Task UpdateData()
    {
        string data = $"{Model.X1},{Model.Y1} {Model.X2},{Model.Y2} {Model.X3},{Model.Y3} {Model.X4},{Model.Y4}";

        await JSRuntime.InvokeVoidAsync("ElementSetAttribute", Ref, "points", data);
    }

    public void Dispose()
    {
        if (Model != null)
        {
            Model.ControlNodePosittionChanged -= UpdateData;
            Model.ActiveChanged -= ActiveChanged;
            Model.TypeChanged -= StateHasChanged;
        }
        if (DotNetObj != null) DotNetObj.Dispose();
        GC.SuppressFinalize(this);
    }
}
