@inject IJSRuntime JSRuntime
@implements IDisposable


<g visibility="@Visibility">
    <circle @ref="Node1Ref" cx="@X1" cy="@Y1" />
    <text x="@X1" y="@(-Y1 - 0.15)">1</text>
    <circle @ref="Node2Ref" cx="@X2" cy="@Y2" />
    <text x="@X2" y="@(-Y2 - 0.15)">2</text>
    <circle @ref="Node3Ref" cx="@X3" cy="@Y3" />
    <text x="@X3" y="@(-Y3 - 0.15)">3</text>
    <circle @ref="Node4Ref" cx="@X4" cy="@Y4" />
    <text x="@X4" y="@(-Y4 - 0.15)">4</text>
</g>

@code {
    private ElementReference Node1Ref;
    private ElementReference Node2Ref;
    private ElementReference Node3Ref;
    private ElementReference Node4Ref;
    private DotNetObjectReference<ZoneControlPoint> DotNetObj = null!;

    private double X1;
    private double Y1;
    private double X2;
    private double Y2;
    private double X3;
    private double Y3;
    private double X4;
    private double Y4;
    private ZoneModel? Model;
    private string Visibility = "hidden";

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

        DotNetObj = DotNetObjectReference.Create(this);
        await JSRuntime.InvokeVoidAsync("AddMouseDownEventListener", DotNetObj, Node1Ref, nameof(OnMouseDownNode1), false);
        await JSRuntime.InvokeVoidAsync("AddMouseDownEventListener", DotNetObj, Node2Ref, nameof(OnMouseDownNode2), false);
        await JSRuntime.InvokeVoidAsync("AddMouseDownEventListener", DotNetObj, Node3Ref, nameof(OnMouseDownNode3), false);
        await JSRuntime.InvokeVoidAsync("AddMouseDownEventListener", DotNetObj, Node4Ref, nameof(OnMouseDownNode4), false);
    }

    public void SetControl(ZoneModel? model)
    {
        if (Model != null)
        {
            Model.ControlNodePosittionChanged -= CaculateZoneAsync;
        }

        Model = model;
        if (Model != null)
        {
            Visibility = "visible";
            CaculateZone();

            Model.ControlNodePosittionChanged += CaculateZoneAsync;
            Visibility = "visible";
        }
        else
        {
            Visibility = "hidden";
        }
        StateHasChanged();
    }

    private Task CaculateZoneAsync()
    {
        CaculateZone();
        return Task.CompletedTask;
    }

    private void CaculateZone()
    {
        if (Model == null) return;

        X1 = Model.X1;
        Y1 = Model.Y1;
        X2 = Model.X2;
        Y2 = Model.Y2;
        X3 = Model.X3;
        Y3 = Model.Y3;
        X4 = Model.X4;
        Y4 = Model.Y4;
        StateHasChanged();
    }

    [JSInvokable]
    public void OnMouseDownNode1(int button, bool altKey, bool ctrlKey, bool shiftKey)
    {
        if (Model != null)
        {
            Model.ActiveNode = 1;
        }
    }

    [JSInvokable]
    public void OnMouseDownNode2(int button, bool altKey, bool ctrlKey, bool shiftKey)
    {
        if (Model != null)
        {
            Model.ActiveNode = 2;
        }
    }

    [JSInvokable]
    public void OnMouseDownNode3(int button, bool altKey, bool ctrlKey, bool shiftKey)
    {
        if (Model != null)
        {
            Model.ActiveNode = 3;
        }
    }

    [JSInvokable]
    public void OnMouseDownNode4(int button, bool altKey, bool ctrlKey, bool shiftKey)
    {
        if (Model != null)
        {
            Model.ActiveNode = 4;
        }
    }


    public void Dispose()
    {
        if (Model != null)
        {
            Model.ControlNodePosittionChanged -= CaculateZoneAsync;
            Model = null;
        }
        if (DotNetObj is not null) DotNetObj.Dispose();
        GC.SuppressFinalize(this);
    }
}
