
@* File: Typewriter.razor *@
@inherits ComponentBase

  @*   <span>@_display</span> *@
   @_display


@code {
    [Parameter] public string Text { get; set; }
    
    public int WordDelay { get; set; } = 100;
    public bool StartOnRender { get; set; } = true;
    // [Parameter] public EventCallback OnFinished { get; set; }

    private string _display = string.Empty;
    private string[] _words = Array.Empty<string>();
    private int _index = 0;
    private CancellationTokenSource? _cts;
    private bool _isRunning = false;

    protected override async Task OnParametersSetAsync()
    {
        // Prepare tokenized words once per parameter set
        _words = string.IsNullOrWhiteSpace(Text)
            ? Array.Empty<string>()
            : System.Text.RegularExpressions.Regex.Split(Text.Trim(), "\\s+");

        if (StartOnRender && !_isRunning && _index == 0)
        {
            await StartAsync();
        }
    }

    /// <summary>
    /// Start typing from the current index.
    /// </summary>
    public async Task StartAsync()
    {
        if (_isRunning) return;
        _cts?.Cancel();
        _cts = new CancellationTokenSource();
        var token = _cts.Token;
        _isRunning = true;

        try
        {
            while (_index < _words.Length && !token.IsCancellationRequested)
            {
                if (_index > 0)
                {
                    _display += " ";
                }
                _display += _words[_index++];
                await InvokeAsync(StateHasChanged);
                await Task.Delay(Math.Max(0, WordDelay), token);
            }
        }
        catch (TaskCanceledException) { }
        finally
        {
            _isRunning = false;
            // if (_index >= _words.Length && OnFinished.HasDelegate)
            // {
            //     await OnFinished.InvokeAsync();
            // }
        }
    }

    /// <summary>
    /// Pause typing (can be resumed with StartAsync()).
    /// </summary>
    public void Pause()
    {
        _cts?.Cancel();
        _isRunning = false;
    }

    /// <summary>
    /// Stop and reset the text to the beginning.
    /// </summary>
    public async Task ResetAsync()
    {
        Pause();
        _display = string.Empty;
        _index = 0;
        await InvokeAsync(StateHasChanged);
    }
}

