docs: public String buildWithMaximumLength(final int maximumPayloadSize) {
          final Map<String, Object> payload = new HashMap<>();
  
          {
              final Map<String, Object> aps = new HashMap<>();
  
              if (this.badgeNumber != null) {
                  aps.put(BADGE_KEY, this.badgeNumber);
              }
  
              if (this.soundFileName != null) {
                  aps.put(SOUND_KEY, this.soundFileName);
              } else if (this.soundForCriticalAlert != null) {
                  aps.put(SOUND_KEY, this.soundForCriticalAlert);
              }
  
              if (this.categoryName != null) {
                  aps.put(CATEGORY_KEY, this.categoryName);
              }
  
              if (this.contentAvailable) {
                  aps.put(CONTENT_AVAILABLE_KEY, 1);
              }
  
              if (this.mutableContent) {
                  aps.put(MUTABLE_CONTENT_KEY, 1);
              }
  
              if (this.threadId != null) {
                  aps.put(THREAD_ID_KEY, this.threadId);
              }
  
              if (this.urlArguments != null) {
                  aps.put(URL_ARGS_KEY, this.urlArguments);
              }
  
              final Map<String, Object> alert = new HashMap<>();
              {
                  if (this.alertBody != null) {
                      alert.put(ALERT_BODY_KEY, this.alertBody);
                  }
  
                  if (this.alertTitle != null) {
                      alert.put(ALERT_TITLE_KEY, this.alertTitle);
                  }
  
                  if (this.alertSubtitle != null) {
                      alert.put(ALERT_SUBTITLE_KEY, this.alertSubtitle);
                  }
  
                  if (this.summaryArgument != null) {
                      alert.put(SUMMARY_ARGUMENT_KEY, this.summaryArgument);
                  }
  
                  if (this.summaryArgumentCount != null) {
                      alert.put(SUMMARY_ARGUMENT_COUNT_KEY, this.summaryArgumentCount);
                  }
  
                  if (this.showActionButton) {
                      if (this.localizedActionButtonKey != null) {
                          alert.put(ACTION_LOC_KEY, this.localizedActionButtonKey);
                      }
  
                      if (this.actionButtonLabel != null) {
                          alert.put(ACTION_KEY, this.actionButtonLabel);
                      }
                  } else {
                      // To hide the action button, the key needs to be present, but the value needs to be null
                      alert.put(ACTION_LOC_KEY, null);
                  }
  
                  if (this.localizedAlertKey != null) {
                      alert.put(ALERT_LOC_KEY, this.localizedAlertKey);
  
                      if (this.localizedAlertArguments != null) {
                          alert.put(ALERT_ARGS_KEY, Arrays.asList(this.localizedAlertArguments));
                      }
                  }
  
                  if (this.localizedAlertTitleKey != null) {
                      alert.put(ALERT_TITLE_LOC_KEY, this.localizedAlertTitleKey);
  
                      if (this.localizedAlertTitleArguments != null) {
                          alert.put(ALERT_TITLE_ARGS_KEY, Arrays.asList(this.localizedAlertTitleArguments));
                      }
                  }
  
                  if (this.localizedAlertSubtitleKey != null) {
                      alert.put(ALERT_SUBTITLE_LOC_KEY, this.localizedAlertSubtitleKey);
  
                      if (this.localizedAlertSubtitleArguments != null) {
                          alert.put(ALERT_SUBTITLE_ARGS_KEY, Arrays.asList(this.localizedAlertSubtitleArguments));
                      }
                  }
  
                  if (this.launchImageFileName != null) {
                      alert.put(LAUNCH_IMAGE_KEY, this.launchImageFileName);
                  }
              }
  
              if (alert.size() == 1 && alert.containsKey(ALERT_BODY_KEY) && this.preferStringRepresentationForAlerts) {
                  aps.put(ALERT_KEY, alert.get(ALERT_BODY_KEY));
              } else if (!alert.isEmpty()) {
                  aps.put(ALERT_KEY, alert);
              }
  
              payload.put(APS_KEY, aps);
          }
  
          for (final Map.Entry<String, Object> entry : this.customProperties.entrySet()) {
              payload.put(entry.getKey(), entry.getValue());
          }
  
          this.buffer.reset();
          GSON.toJson(payload, this.buffer);
  
          final String payloadString = this.buffer.toString();
          final int initialPayloadSize = payloadString.getBytes(StandardCharsets.UTF_8).length;
  
          final String fittedPayloadString;
  
          if (initialPayloadSize <= maximumPayloadSize) {
              fittedPayloadString = payloadString;
          } else {
              if (this.alertBody != null) {
                  this.replaceMessageBody(payload, "");
  
                  this.buffer.reset();
                  GSON.toJson(payload, this.buffer);
  
                  final int payloadSizeWithEmptyMessage = this.buffer.toString().getBytes(StandardCharsets.UTF_8).length;
  
                  if (payloadSizeWithEmptyMessage >= maximumPayloadSize) {
                      throw new IllegalArgumentException("Payload exceeds maximum size even with an empty message body.");
                  }
  
                  final int maximumEscapedMessageBodySize = maximumPayloadSize - payloadSizeWithEmptyMessage -
                          ABBREVIATION_SUBSTRING.getBytes(StandardCharsets.UTF_8).length;
  
                  final String fittedMessageBody = this.alertBody.substring(0,
                          ApnsPayloadBuilder.getLengthOfJsonEscapedUtf8StringFittingSize(this.alertBody, maximumEscapedMessageBodySize));
  
                  this.replaceMessageBody(payload, fittedMessageBody + ABBREVIATION_SUBSTRING);
  
                  this.buffer.reset();
                  GSON.toJson(payload, this.buffer);
  
                  fittedPayloadString = this.buffer.toString();
              } else {
                  throw new IllegalArgumentException(String.format(
                          "Payload size is %d bytes (with a maximum of %d bytes) and cannot be shortened.",
                          initialPayloadSize, maximumPayloadSize));
              }
          }
  
          return fittedPayloadString;
      }