using InnovEnergy.Lib.Utils;

namespace InnovEnergy.Lib.Channels.Framed;


public class Channel<Tx, Rx> :  Connection
{
    private readonly AsyncAction<Tx> _Transmit;
    private readonly Async<Rx>       _Receive;

    public Channel(AsyncAction<Tx> transmit,
                         Async<Rx> receive, 
                      AsyncAction? open  = null, 
                      AsyncAction? close = null,
                        CloseAfter closeAfter = CloseAfter.Error)
        : 
        base(open, close, closeAfter)
    {
        _Transmit = transmit;
        _Receive  = receive;
    }

    public async Task Transmit(Tx data)
    {
        try
        {
            await Open();
            await _Transmit(data);
            await CloseAfterTransmit();
        }
        catch 
        {
            await CloseAfterError();
            throw;
        }
    }

    public async Task<Rx> Receive()
    {
        try
        {
            await Open();
            var data = await _Receive();
            await CloseAfterReceive();
            return data;
        }
        catch
        {
            await CloseAfterError();
            throw;
        }
    }
}

public class Channel<T> : Channel<T, T>
{
    public Channel(AsyncAction<T> transmit,
                         Async<T> receive, 
                     AsyncAction? open  = null, 
                     AsyncAction? close = null,
                       CloseAfter closeAfter = CloseAfter.Error) 
        : 
        base(transmit, receive, open, close, closeAfter)
    {
    }
}