// TODO: handleSMPMessage
  private void handleSMPMessage(
      MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureSMPMessage message) {
    Pair<Long, Long> messageAndThreadId;

    // TODO: make this a boolean flag
    Log.d(TAG, "handleSMPMessage isSMPSyncMessage: " + message.isSMPSyncMessage());
    if (message.isSMPSyncMessage()) {
      Log.d(TAG, "isSMPSyncContext: true");
      messageAndThreadId = insertSyncSMPMessage(masterSecret, envelope, message);
    } else {
      Log.d(TAG, "isStandardSMPMessage: true");
      messageAndThreadId = insertStandardSMPMessage(masterSecret, envelope, message);
    }

    MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
  }
  // TODO: build correct method logic here
  private Pair<Long, Long> insertSyncSMPMessage(
      MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureSMPMessage message) {

    EncryptingSMPDatabase database = DatabaseFactory.getEncryptingSMPDatabase(context);
    String body = message.getBody().isPresent() ? message.getBody().get() : "";

    IncomingSMPMessage smpMessage =
        new IncomingSMPMessage(
            envelope.getSource(),
            envelope.getSourceDevice(),
            message.getTimestamp(),
            body,
            message.getGroupInfo());

    smpMessage = new IncomingEncryptedSMPSyncMessage(smpMessage, body);

    return database.insertMessageInbox(masterSecret, smpMessage);
  }
  private void handleMessage(
      MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
    try {
      AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret);
      TextSecureAddress localAddress =
          new TextSecureAddress(TextSecurePreferences.getLocalNumber(context));
      TextSecureSMPCipher cipher = new TextSecureSMPCipher(localAddress, axolotlStore);

      TextSecureSMPMessage message = cipher.decrypt(envelope);

      Log.d(TAG, "handleMessage() isSMPMessage: " + message.isSMPMessage());

      if (message.isEndSession())
        handleEndSessionMessage(masterSecret, envelope, message, smsMessageId);
      else if (message.isGroupUpdate())
        handleGroupMessage(masterSecret, envelope, message, smsMessageId);
      else if (message.getAttachments().isPresent())
        handleMediaMessage(masterSecret, envelope, message, smsMessageId);

      // TODO: handleSMPMessage
      else if (message.isSMPMessage()) handleSMPMessage(masterSecret, envelope, message);
      else handleTextMessage(masterSecret, envelope, message, smsMessageId);

      if (envelope.isPreKeyWhisperMessage()) {
        ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
      }
    } catch (InvalidVersionException e) {
      Log.w(TAG, e);
      handleInvalidVersionMessage(masterSecret, envelope, smsMessageId);
    } catch (InvalidMessageException
        | InvalidKeyIdException
        | InvalidKeyException
        | MmsException e) {
      Log.w(TAG, e);
      handleCorruptMessage(masterSecret, envelope, smsMessageId);
    } catch (NoSessionException e) {
      Log.w(TAG, e);
      handleNoSessionMessage(masterSecret, envelope, smsMessageId);
    } catch (LegacyMessageException e) {
      Log.w(TAG, e);
      handleLegacyMessage(masterSecret, envelope, smsMessageId);
    } catch (DuplicateMessageException e) {
      Log.w(TAG, e);
      handleDuplicateMessage(masterSecret, envelope, smsMessageId);
    } catch (UntrustedIdentityException e) {
      Log.w(TAG, e);
      handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId);
    }
  }