require 'uri'

module Hypertube
  module Core
    module Http2Client
      class Http2Client
        @clients = {}
        @clients_lock = Mutex.new

        class << self
          def send_message(connection_data, message)
            raise ArgumentError, 'connection_data cannot be nil' if connection_data.nil?
            raise ArgumentError, 'message cannot be nil' if message.nil?

            client = create_or_get_client(connection_data, expected_current: nil)
            client.with_send_receive_lock do
              # TODO: Use framework HTTP/2 client in a later step.
              # Keep this client as skeleton for now.
              return []
            end
          end

          def close(connection_data)
            @clients_lock.synchronize do
              @clients.delete(connection_key(connection_data))
            end
          end

          def get_state(connection_data)
            @clients_lock.synchronize do
              @clients.key?(connection_key(connection_data)) ? :OPEN : nil
            end
          end

          private

          def connection_key(connection_data)
            if connection_data.respond_to?(:to_canonical_key)
              return connection_data.to_canonical_key
            end
            url = connection_data.respond_to?(:hostname) ? connection_data.hostname : connection_data.to_s
            "http2|#{url}"
          end

          def create_or_get_client(connection_data, expected_current:)
            @clients_lock.synchronize do
              key = connection_key(connection_data)
              if expected_current.nil?
                return @clients[key] if @clients[key]
                created = new(connection_data)
                @clients[key] = created
                return created
              end

              current = @clients[key]
              @clients.delete(key) if current&.equal?(expected_current)
              recreated = new(connection_data)
              @clients[key] = recreated
              recreated
            end
          end
        end

        def initialize(connection_data)
          @connection_data = connection_data
          @send_receive_lock = Mutex.new
        end

        def with_send_receive_lock
          @send_receive_lock.synchronize { yield }
        end
      end
    end
  end
end
