@implements IAsyncDisposable

@using Microsoft.CodeAnalysis

@inject ProcessorHubClient processorHub
@inject ISnackbar Snackbar
@inject IDialogService DialogService

<div class="w-100 h-100 d-flex flex-column">
    <div class="d-flex flex-row-reverse">
        <div class="mx-1"></div>
        <ActionButton Icon="mdi-stop text-danger" Large Tooltip="Stop" Disabled="@StopDisable" OnClick="Stop" />
        <ActionButton Icon="mdi-play text-success" Large Tooltip="Run" Disabled="@RunDisable" OnClick="Run" />
        <ActionButton Icon="mdi-cog-play text-primary" Large Tooltip="Build" Disabled="@BuildDisable" OnClick="Build" />
        <ActionButton Icon="mdi-refresh text-primary" Large Tooltip="Reset" Disabled="@ResetDisable" OnClick="Reset" />
        <ActionButton Icon="mdi-receipt-text-remove" Large Tooltip="Clear console" OnClick="ClearConsole" />
    </div>
    <div class="w-100 flex-grow-1">
        <ProcessorConsole @ref="processorConsole" />
    </div>
</div>

@code {
    [CascadingParameter]
    private ScriptWorkspace Workspace { 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()
    {
        processorHub.StateChanged += OnStateChanged;
        processorHub.RequestChanged += OnRequestChanged;
        await processorHub.StartAsync();

        OnStateChanged(await processorHub.GetState());
    }

    private void OnStateChanged(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()
    {
        if (Workspace.AnyChanges())
        {
            bool? confirm = await DialogService.ShowMessageBox("Cảnh báo", "Bạn có muốn lưu lại tất cả thay đổi trước khi build không?", yesText: "Save All", cancelText: "Cancel");

            if (confirm != true) return;

            bool isError = false;
            var saveResults = await Workspace.SaveAllAsync();
            foreach (var saveResult in saveResults)
            {
                if (!saveResult.IsSuccess)
                {
                    if (processorConsole != null)
                    {
                        processorConsole.AddError(saveResult.Message);
                    }
                    else
                    {
                        Snackbar.Add(saveResult.Message, Severity.Error);
                    }
                    isError = true;
                }
            }

            if (isError)
            {
                return;
            }
            else
            {
                await Task.Delay(500);
            }
        }

        var diagnostics = await Workspace.GetAllDiagnostics();
        if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Warning || d.Severity == DiagnosticSeverity.Error))
        {
            foreach (var diagnostic in diagnostics)
            {
                if (diagnostic.Severity == DiagnosticSeverity.Warning)
                {
                    if (processorConsole != null)
                    {
                        processorConsole.AddWarning($"File /{diagnostic}");
                    }
                    else
                    {
                        Snackbar.Add($"File /{diagnostic}", Severity.Warning);
                    }
                }
                else if (diagnostic.Severity == DiagnosticSeverity.Error)
                {
                    if (processorConsole != null)
                    {
                        processorConsole.AddError($"File /{diagnostic}");
                    }
                    else
                    {
                        Snackbar.Add($"File /{diagnostic}", Severity.Error);
                    }
                }
            }
        }
        else
        {
            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 async ValueTask DisposeAsync()
    {
        processorHub.StateChanged -= OnStateChanged;
        processorHub.RequestChanged -= OnRequestChanged;
        await processorHub.StopAsync();
    }
}
