docs: @SuppressWarnings("unchecked")
      public <T extends ApnsPushNotification> PushNotificationFuture<T, PushNotificationResponse<T>> sendNotification(final T notification) {
          final PushNotificationFuture<T, PushNotificationResponse<T>> responseFuture;
  
          if (!this.isClosed.get()) {
              final PushNotificationPromise<T, PushNotificationResponse<T>> responsePromise =
                      new PushNotificationPromise<>(this.eventLoopGroup.next(), notification);
  
              final long notificationId = this.nextNotificationId.getAndIncrement();
  
              this.channelPool.acquire().addListener(new GenericFutureListener<Future<Channel>>() {
                  @Override
                  public void operationComplete(final Future<Channel> acquireFuture) throws Exception {
                      if (acquireFuture.isSuccess()) {
                          final Channel channel = acquireFuture.getNow();
  
                          channel.writeAndFlush(responsePromise).addListener(new GenericFutureListener<ChannelFuture>() {
  
                              @Override
                              public void operationComplete(final ChannelFuture future) throws Exception {
                                  if (future.isSuccess()) {
                                      ApnsClient.this.metricsListener.handleNotificationSent(ApnsClient.this, notificationId);
                                  }
                              }
                          });
  
                          ApnsClient.this.channelPool.release(channel);
                      } else {
                          responsePromise.tryFailure(acquireFuture.cause());
                      }
                  }
              });
  
              responsePromise.addListener(new PushNotificationResponseListener<T>() {
                  @Override
                  public void operationComplete(final PushNotificationFuture<T, PushNotificationResponse<T>> future) throws Exception {
                      if (future.isSuccess()) {
                          final PushNotificationResponse response = future.getNow();
  
                          if (response.isAccepted()) {
                              ApnsClient.this.metricsListener.handleNotificationAccepted(ApnsClient.this, notificationId);
                          } else {
                              ApnsClient.this.metricsListener.handleNotificationRejected(ApnsClient.this, notificationId);
                          }
                      } else {
                          ApnsClient.this.metricsListener.handleWriteFailure(ApnsClient.this, notificationId);
                      }
                  }
              });
  
              responseFuture = responsePromise;
          } else {
              final PushNotificationPromise<T, PushNotificationResponse<T>> failedPromise =
                      new PushNotificationPromise<>(GlobalEventExecutor.INSTANCE, notification);
  
              failedPromise.setFailure(CLIENT_CLOSED_EXCEPTION);
  
              responseFuture = failedPromise;
          }
  
          return responseFuture;
      }