using System.IO.Pipes;
using Microsoft.Extensions.Logging;
using TagashiFileHub.Communication.Abstractions;

namespace TagashiFileHub.Communication.IPC;

public class TagashiClient : ITagashiClient, IDisposable
{
    private readonly ILogger<TagashiClient>? _logger;

    public TagashiClient(ILogger<TagashiClient>? logger)
    {
        _logger = logger;
    }

    private CancellationTokenSource DisconnectingSource { get; } = new();

    private NamedPipeClientStream? ClientPipe { get; set; }

    public void Dispose()
    {
        TryDisconnectCurrentPipe();
    }

    private void TryDisconnectCurrentPipe()
    {
        _logger?.LogInformation("Closing current pipe connection if existing.");
        DisconnectingSource.Cancel(false);
        ClientPipe?.Close();
        ClientPipe?.Dispose();
        ClientPipe = null;
    }

    public async Task ConnectAsync(string pipeName)
    {
        if (ClientPipe is not null)
        {
            _logger?.LogWarning("Client pipe already opened.");
            TryDisconnectCurrentPipe();
        }

        _logger?.LogInformation($"Creating pipe for \".\" with name \"{pipeName}\"");
        ClientPipe = new NamedPipeClientStream(".", IpcUtils.PipeName(pipeName), PipeDirection.InOut, PipeOptions.None);

        await ClientPipe.ConnectAsync().ConfigureAwait(false);

        DisconnectingSource.TryReset();
        _ = NewListenTask(ClientPipe, DisconnectingSource.Token);
    }

    private static Task NewListenTask(NamedPipeClientStream clientPipe, CancellationToken cancellationToken)
    {
        return Task.Factory.StartNew(async () =>
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                using var reader = new StreamReader(clientPipe);

                var message = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
            }
        }, cancellationToken);
    }
}