class W3DHub
 class WebSocketClient
   def initialize
     @errored = nil
     @connection = nil

     @events = {
       open: nil,
       message: nil,
       close: nil,
       error: nil
     }
   end

   def connect(endpoint, headers: nil, &block)
     yield(self)

     Sync do |task|
      endpoint = Async::HTTP::Endpoint.parse(endpoint, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)

      Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|
        @connection = connection

        @events[:open]&.call

        while message = connection.read
          @events[:message].call(message)
        end
      # FIXME: Don't rescue for all ta errors?
      rescue => error
        @errored = true
        @events[:error]&.call(error)
      ensure
        @events[:close]&.call unless @errored
        @connection = nil
        @errored = false
      end
     end

     self
   end

   def on(event, &block)
     raise "Event must be a symbol" unless event.is_a?(Symbol)
     raise "Unknown event: #{event.inspect}" unless @events.keys.include?(event)
     raise "No block given for #{event.inspect}" unless block_given?

     @events[event] = block
   end

   def send(data, type: :text)
     @connection&.write(data)
     @connection&.flush
   end

   def close
     @connection&.close
   end

   def open?
     !closed?
   end

   def closed?
     @connection&.closed?
   end
 end
end
