@implements IDisposable

@inject IHttpClientFactory HttpFactory
@inject IJSRuntime JSRuntime

<g class="element" visibility="@(Show ? "visible" : "hidden")" @ondblclick="@(async () =>  await DoubleClick.InvokeAsync(Model))">
    <image @ref="@ImageRef" />
    <text @ref="textRef" visibility="@(Show && ShowName ? "visible" : "hidden")">@Model?.Name</text>
</g>


@code {
    [Parameter]
    public bool Show { get; set; }

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

    [Parameter, EditorRequired]
    public ElementModel Model { get; set; } = null!;

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

    private ElementReference ImageRef;
    private ElementReference textRef;
    private ElementModelDto ElementModel = new();

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

        using var Http = HttpFactory.CreateClient("MapManagerAPI");
        var model = await Http.GetFromJsonAsync<MessageResult<ElementModelDto?>>($"api/ElementModels/{Model.ModelId}");
        if (model is not null && model.Data is not null)
        {
            await JSRuntime.InvokeVoidAsync("SetImageAttribute", ImageRef, model.Data.Width, model.Data.Height, -model.Data.Width / 2, -model.Data.Height / 2, $"{Http.BaseAddress}api/images/elementModel/{model.Data.Id}?IsOpen={Model.IsOpen}");
            ElementModel = model.Data;
        }
        if (Model is not null)
        {
            Model.UpdateChanged += Model_UpdateChanged;
            await UpdatePosition(Model.X, Model.Y, Model.Theta);
        }
    }

    private async Task Model_UpdateChanged()
    {
        await SetElementImage(Model.IsOpen);
        await UpdatePosition(Model.OffsetX, Model.OffsetY);
    }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        bool updateRobot = false;
        if (parameters.TryGetValue(nameof(Model), out ElementModel? model) && ((Model?.Id ?? Guid.Empty) != (model?.Id ?? Guid.Empty)))
        {
            if (Model != null) Model.UpdateChanged -= Model_UpdateChanged;
            if (model != null)
            {
                updateRobot = true;
                model.UpdateChanged -= Model_UpdateChanged;
            }
        }
        await base.SetParametersAsync(parameters);
        if (updateRobot && model != null)
        {
            await SetElementImage(model.IsOpen);
            await UpdatePosition(model.X, model.Y, model.Theta);
        }
    }

    private async Task SetElementImage(bool isOpen)
    {
        if (ElementModel.Id != Guid.Empty)
        {
            using var Http = HttpFactory.CreateClient("MapManagerAPI");
            await JSRuntime.InvokeVoidAsync("SetImageAttribute", ImageRef, ElementModel.Width, ElementModel.Height, (-ElementModel.Width / 2), (-ElementModel.Height / 2), $"{Http.BaseAddress}api/images/elementModel/{ElementModel.Id}?IsOpen={isOpen}");
        }
    }

    public async Task UpdatePosition(double x, double y, double theta)
        => await JSRuntime.InvokeVoidAsync("SetRobotPosition", ImageRef, textRef, x + Model.OffsetX, y + Model.OffsetY, theta, -ElementModel.Width / 2, -ElementModel.Height / 2);

    public async Task UpdatePosition(double offsetX, double offsetY)
        => await JSRuntime.InvokeVoidAsync("SetRobotPosition", ImageRef, textRef, Model.X + offsetX, Model.Y + offsetY, Model.Theta, -ElementModel.Width / 2, -ElementModel.Height / 2);


    public void Dispose()
    {
        if (Model != null) Model.UpdateChanged -= Model_UpdateChanged;
        GC.SuppressFinalize(this);
    }
}
