@implements IAsyncDisposable

@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using RobotNet.WebApp.Clients

@inject RobotHubClient RobotHub
@inject ISnackbar Snackbar
@inject IHttpClientFactory HttpFactory

<MudCard Class="w-100 me-2" Elevation="0" Outlined Style="height: 450px">
    <MudCardHeader>
        <MudText Typo="Typo.h5">Test</MudText>
    </MudCardHeader>
    <MudCardContent>
        <div class="d-flex flex-column">
            <div class="d-flex flex-row my-2">
                <div class="d-flex flex-row" style="width: 415px">
                    @* <MudAutocomplete T="NodeDto" Variant="Variant.Outlined" Label="Node" Disabled="!Robot.Online" SearchFunc="NodeSearch"
                                     MaxItems="@Nodes.Count" ToStringFunc="@(e=> e == null ? null : $"{e.Name}")" ValueChanged="NodeChanged" ShowProgressIndicator="true">
                        <NoItemsTemplate>
                            <MudText Align="Align.Center" Class="px-4 py-1">
                                No items found
                            </MudText>
                        </NoItemsTemplate>
                    </MudAutocomplete> *@
                    <MudSelect T="NodeDto" Label="Node" Variant="Variant.Outlined" MultiSelection="true" SelectAll="true" SelectAllText="Select all nodes" Disabled="!Robot.Online"
                               @bind-SelectedValues="PreSelectedNodes" HelperText="@($"{PreSelectedNodes.Count()} node{(PreSelectedNodes.Count() > 1 ? "s have" : " has")} been selected")">
                        @foreach (var node in Nodes)
                        {
                            <MudSelectItem T="NodeDto" Value="@node">@node.Name</MudSelectItem>
                        }
                    </MudSelect>
                </div>
                <div class="d-flex flex-grow-1 mt-2 mb-7 ms-2">
                    <MudButton Class="w-100" Variant="Variant.Filled" Color="Color.Info" Disabled="@(!Robot.Online)" OnClick="AddNode">Add</MudButton>
                </div>
            </div>
            <div class="paper-nodes">
                @foreach (var node in SelectedNodes)
                {
                    <div class="m-1" style="height: fit-content">
                        <MudButton Variant="Variant.Filled" Color="Color.Info" Style="text-transform:none" OnClick="@(() => SelectedNodes.Remove(node))">
                            @(node.Name)
                        </MudButton>
                    </div>
                }
            </div>
            <div class="d-flex w-100 flex-row my-2">
                <MudButton Class="d-flex mt-2 mb-1" Variant="Variant.Filled" Color="Color.Info" Disabled="@(!Robot.Online || IsWorking)" OnClick="Run">Run</MudButton>
                <MudButton Class="d-flex mt-2 mb-1 ms-2" Variant="Variant.Filled" Color="Color.Secondary" Disabled="@(!Robot.Online)" OnClick="Cancel">Cancel</MudButton>
            </div>
        </div>
    </MudCardContent>
</MudCard>

@code {
    [Parameter, EditorRequired]
    public RobotDto Robot { get; set; } = new();

    // private NodeDto? SelectedNode;

    private List<NodeDto> Nodes = [];
    private bool IsWorking = false;
    private List<NodeDto> SelectedNodes = [];
    private IEnumerable<NodeDto> PreSelectedNodes = new HashSet<NodeDto>();
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (!firstRender) return;

        await RobotHub.StartAsync();
    }

    public void UpdateState(bool isOnline, bool isWorking)
    {
        Robot.Online = isOnline;
        IsWorking = isWorking;
        StateHasChanged();
    }

    public async Task LoadNodes()
    {
        try
        {
            using var Http = HttpFactory.CreateClient("MapManagerAPI");
            var result = await Http.GetFromJsonAsync<NodeDto[]>($"api/Nodes/{Robot.MapId}");
            if (result is not null) Nodes = result.Where(n => !string.IsNullOrEmpty(n.Name)).ToList();
        }
        catch (AccessTokenNotAvailableException ex)
        {
            ex.Redirect();
        }
    }

    private async Task<IEnumerable<NodeDto>> NodeSearch(string value, CancellationToken token)
    {
        await Task.Delay(5, token);

        if (string.IsNullOrEmpty(value))
        {
            return Nodes.Select(n => n);
        }

        return Nodes.Where(x => x.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(n => n);
    }

    // private void NodeChanged(List<NodeDto> value)
    // {
    //     if (SelectedNode is null || value.Id != SelectedNode.Id) SelectedNode = value;
    // }

    private void AddNode()
    {
        // if (SelectedNode is not null && !SelectedNodes.Contains(SelectedNode))
        // {
        //     SelectedNodes.Add(SelectedNode);
        //     StateHasChanged();
        // }
        if (PreSelectedNodes.Any())
        {
            SelectedNodes.Clear();
            SelectedNodes.AddRange(PreSelectedNodes);
            StateHasChanged();
        }
    }

    private async Task Cancel()
    {
        var result = await RobotHub.CancelNavigation(Robot.RobotId);
        if (result.IsSuccess) Snackbar.Add("Ra lệnh thành công", Severity.Success);
        else Snackbar.Add($"Ra lệnh không thành công: {result.Message}", Severity.Warning);
        StateHasChanged();
    }

    private async Task Run()
    {
        var result = await RobotHub.MoveRandom(Robot.RobotId, [.. SelectedNodes.Select(n => n.Name)]);
        if (result.IsSuccess) Snackbar.Add("Ra lệnh thành công", Severity.Success);
        else Snackbar.Add($"Ra lệnh không thành công: {result.Message}", Severity.Warning);
        StateHasChanged();
    }

    public async ValueTask DisposeAsync()
    {
        await RobotHub.StopAsync();
    }
}
