@using Microsoft.AspNetCore.SignalR.Client
@using Microsoft.CodeAnalysis
@implements IDisposable

@inject ISnackbar Snackbar
@inject IDialogService DialogService

<div class="w-100">
    <MudCard Class="m-2" Style="height: 300px" Elevation="6">
        <MudCardHeader>
            <CardHeaderContent>
                <MudText Typo="Typo.h6">Process Controller - @State</MudText>
            </CardHeaderContent>
            <CardHeaderActions>
                <ActionButton Icon="mdi-receipt-text-remove" Large Tooltip="Clear console" OnClick="ClearConsole" />
                <ActionButton Icon="mdi-refresh text-primary" Large Tooltip="Reset" Disabled="@ResetDisable" OnClick="Reset" />
                <ActionButton Icon="mdi-cog-play text-primary" Large Tooltip="Build" Disabled="@BuildDisable" OnClick="Build" />
                <ActionButton Icon="mdi-play text-success" Large Tooltip="Run" Disabled="@RunDisable" OnClick="Run" />
                <ActionButton Icon="mdi-stop text-danger" Large Tooltip="Stop" Disabled="@StopDisable" OnClick="Stop" />
            </CardHeaderActions>
        </MudCardHeader>
        <MudCardContent>
            <ProcessorConsole @ref="processorConsole" />
        </MudCardContent>
    </MudCard>
</div>

@code {
    [CascadingParameter]
    private ProcessorHubClient ProcessorHub { get; set; } = null!;

    private ProcessorConsole? processorConsole;
    public ProcessorState State { get; private set; } = ProcessorState.Idle;
    private ProcessorRequest Request = ProcessorRequest.None;

    private bool ResetDisable => State != ProcessorState.Idle && State != ProcessorState.Ready && State != ProcessorState.Error && State != ProcessorState.BuildError;
    private bool BuildDisable => State != ProcessorState.Idle && State != ProcessorState.Ready && State != ProcessorState.Error && State != ProcessorState.BuildError;
    private bool RunDisable => State != ProcessorState.Ready;
    private bool StopDisable => State != ProcessorState.Running;

    protected override async Task OnInitializedAsync()
    {
        if (ProcessorHub.IsConnected)
        {
            OnProcessorStateChanged(await ProcessorHub.GetState());
        }

        ProcessorHub.StateChanged += OnProcessorStateChanged;
        ProcessorHub.RequestChanged += OnRequestChanged;
        ProcessorHub.ConnectionStateChanged += OnConnectionStateChanged;
        await base.OnInitializedAsync();
    }

    private void OnConnectionStateChanged(HubConnectionState state)
    {
        if (state == HubConnectionState.Connected)
        {
            _ = InvokeAsync(async Task () =>
            {
                OnProcessorStateChanged(await ProcessorHub.GetState());
            });

        }
    }

    private void OnProcessorStateChanged(ProcessorState state)
    {
        if (State == state) return;

        State = state;
        StateHasChanged();
    }

    private void OnRequestChanged(ProcessorRequest request)
    {
        Request = request;
        StateHasChanged();
    }

    private async Task Reset()
    {
        var result = await ProcessorHub.Reset();
        if (!result.IsSuccess)
        {
            Snackbar.Add($"Failed to reset processor: {result.Message}", Severity.Error);
        }
    }

    private async Task Build()
    {
        var result = await ProcessorHub.Build();
        if (!result.IsSuccess)
        {
            Snackbar.Add($"Failed to build processor: {result.Message}", Severity.Error);
        }
    }

    private async Task Run()
    {
        var result = await ProcessorHub.Run();
        if (!result.IsSuccess)
        {
            Snackbar.Add($"Failed to run processor: {result.Message}", Severity.Error);
        }
    }

    private async Task Stop()
    {
        var result = await ProcessorHub.Stop();
        if (!result.IsSuccess)
        {
            Snackbar.Add($"Failed to stop processor: {result.Message}", Severity.Error);
        }
    }

    private void ClearConsole()
    {
        processorConsole?.Clear();
    }

    public void Dispose()
    {
        ProcessorHub.StateChanged -= OnProcessorStateChanged;
        ProcessorHub.RequestChanged -= OnRequestChanged;
        ProcessorHub.ConnectionStateChanged -= OnConnectionStateChanged;
    }
}
