using H.Pipes;
using InABox.Core;

namespace InABox.IPC
{
    public class RPCClientPipeTransport : RPCClientTransport, IDisposable
    {
        private PipeClient<RPCMessage> Client;
        
        public RPCClientPipeTransport(string name)
        {
            Client = new PipeClient<RPCMessage>(name);
            Client.Connected += Client_Connected;
            Client.Disconnected += Client_Disconnected;
            Client.MessageReceived += Client_MessageReceived;
            Client.ExceptionOccurred += Client_ExceptionOccurred;
        }

        public override void Connect()
        {
            Client.ConnectAsync();
        }
        
        public override void Disconnect()
        {
            Client.DisconnectAsync();
        }

        public override void Send(RPCMessage message)
        {
            Client.WriteAsync(message);
        }

        private void Client_Connected(object? sender, H.Pipes.Args.ConnectionEventArgs<RPCMessage> e)
        {
            DoOpen();
        }
        
        private void Client_Disconnected(object? sender, H.Pipes.Args.ConnectionEventArgs<RPCMessage> e)
        {
            DoClose(RPCTransportCloseEventType.Closed);
        }
        
        private void Client_ExceptionOccurred(object? sender, H.Pipes.Args.ExceptionEventArgs e)
        {
            Logger.Send(LogType.Error, "", $"Exception occured: {e.Exception.Message}");
        }

        
        private void Client_MessageReceived(object? sender, H.Pipes.Args.ConnectionMessageEventArgs<RPCMessage?> e)
        {
            Accept(e.Message);
        }
        
        public void Dispose()
        {
            Client.DisposeAsync().AsTask().Wait();
        }

        ~RPCClientPipeTransport()
        {
            Dispose();
        }
    }
}