namespace Mlaumcherb.Client.Avalonia.сеть;

public class NetworkTask : IDisposable
{
    public readonly string Name;

    public enum Status
    {
        Initialized,
        Started,
        Completed,
        Cancelled,
        Failed
    };

    public Status DownloadStatus { get; private set; } = Status.Initialized;

    public event Action? OnStart; 
    public event Action<DownloadProgress>? OnProgress;
    public event Action<Status>? OnStop; 

    public delegate Task DownloadAction(NetworkProgressReporter progressReporter, CancellationToken ct);

    private readonly DownloadAction _downloadAction;
    private CancellationTokenSource _cts = new();
    private NetworkProgressReporter _progressReporter;

    public NetworkTask(string name, long dataSize, DownloadAction downloadAction)
    {
        Name = name;
        _downloadAction = downloadAction;
        _progressReporter = new NetworkProgressReporter(dataSize, ReportProgress);
    }
    
    private void ReportProgress(DownloadProgress p) => OnProgress?.Invoke(p);

    public async Task StartAsync()
    {
        if(DownloadStatus == Status.Started || DownloadStatus == Status.Completed)
            return;
        DownloadStatus = Status.Started;
        try
        {
            _progressReporter.Start();
            OnStart?.Invoke();
            await _downloadAction(_progressReporter, _cts.Token);
            DownloadStatus = Status.Completed;
        }
        catch (OperationCanceledException)
        {
            DownloadStatus = Status.Cancelled;
        }
        catch
        {
            DownloadStatus = Status.Failed;
            throw;
        }
        finally
        {
            _progressReporter.Stop();
            OnStop?.Invoke(DownloadStatus);
        }
    } 

    public void Cancel()
    {
        DownloadStatus = Status.Cancelled;
        _cts.Cancel();
        _cts = new CancellationTokenSource();
    }

    public void Dispose()
    {
        _cts.Dispose();
        _progressReporter.Dispose();
    }
}