MessageItem(Context context, String type, Cursor cursor, ColumnsMap columnsMap, String highlight)
      throws MmsException {
    mContext = context;
    mMsgId = cursor.getLong(columnsMap.mColumnMsgId);
    mHighlight = highlight != null ? highlight.toLowerCase() : null;
    mType = type;

    if ("sms".equals(type)) {
      mReadReport = false; // No read reports in sms

      long status = cursor.getLong(columnsMap.mColumnSmsStatus);
      if (status == Sms.STATUS_NONE) {
        // No delivery report requested
        mDeliveryStatus = DeliveryStatus.NONE;
      } else if (status >= Sms.STATUS_FAILED) {
        // Failure
        mDeliveryStatus = DeliveryStatus.FAILED;
      } else if (status >= Sms.STATUS_PENDING) {
        // Pending
        mDeliveryStatus = DeliveryStatus.PENDING;
      } else {
        // Success
        mDeliveryStatus = DeliveryStatus.RECEIVED;
      }

      mMessageUri = ContentUris.withAppendedId(Sms.CONTENT_URI, mMsgId);
      // Set contact and message body
      mBoxId = cursor.getInt(columnsMap.mColumnSmsType);
      mAddress = cursor.getString(columnsMap.mColumnSmsAddress);
      if (Sms.isOutgoingFolder(mBoxId)) {
        String meString = context.getString(R.string.messagelist_sender_self);

        mContact = meString;
      } else {
        // For incoming messages, the ADDRESS field contains the sender.
        mContact = Contact.get(mAddress, false).getName();
      }
      mBody = cursor.getString(columnsMap.mColumnSmsBody);

      if (isEncrypted()) {
        encrypted = true;
        if (MessageEncryptionFactory.isAuthenticated()) {
          try {
            mBody = MessageEncryptionFactory.stripHeader(mBody);
            mBody = MessageEncryption.decrypt(context, mAddress, Base64.decode(mBody));
          } catch (Exception e) {
            Log.e(TAG, "Error decrypting message");
            e.printStackTrace();
          }
        } else if (ComposeMessageActivity.encryptIfNeeded
            && !MessageEncryptionFactory.isAuthenticating()) {
          ComposeMessageActivity.encryptIfNeeded = false;
          MessageEncryptionFactory.setAuthenticating(true);
          Intent intent = new Intent(context, AuthenticateActivity.class);
          context.startActivity(intent);
        }
      } else if (isPublicKey()) {
        publickey = true;
        mBody = context.getString(R.string.parandroid_public_key_snippet);
      }

      if (!isOutgoingMessage()) {
        // Set "sent" time stamp
        long date = cursor.getLong(columnsMap.mColumnSmsDate);
        mTimestamp =
            String.format(
                context.getString(R.string.sent_on),
                MessageUtils.formatTimeStampString(context, date));
      }

      mLocked = cursor.getInt(columnsMap.mColumnSmsLocked) != 0;
    } else if ("mms".equals(type)) {
      mMessageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, mMsgId);
      mBoxId = cursor.getInt(columnsMap.mColumnMmsMessageBox);
      mMessageType = cursor.getInt(columnsMap.mColumnMmsMessageType);
      mErrorType = cursor.getInt(columnsMap.mColumnMmsErrorType);
      String subject = cursor.getString(columnsMap.mColumnMmsSubject);
      if (!TextUtils.isEmpty(subject)) {
        EncodedStringValue v =
            new EncodedStringValue(
                cursor.getInt(columnsMap.mColumnMmsSubjectCharset), PduPersister.getBytes(subject));
        mSubject = v.getString();
      }
      mLocked = cursor.getInt(columnsMap.mColumnMmsLocked) != 0;

      long timestamp = 0L;
      PduPersister p = PduPersister.getPduPersister(mContext);
      if (PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND == mMessageType) {
        mDeliveryStatus = DeliveryStatus.NONE;
        NotificationInd notifInd = (NotificationInd) p.load(mMessageUri);
        interpretFrom(notifInd.getFrom(), mMessageUri);
        // Borrow the mBody to hold the URL of the message.
        mBody = new String(notifInd.getContentLocation());
        mMessageSize = (int) notifInd.getMessageSize();
        timestamp = notifInd.getExpiry() * 1000L;
      } else {
        MultimediaMessagePdu msg = (MultimediaMessagePdu) p.load(mMessageUri);
        mSlideshow = SlideshowModel.createFromPduBody(context, msg.getBody());
        mAttachmentType = MessageUtils.getAttachmentType(mSlideshow);

        if (mMessageType == PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF) {
          RetrieveConf retrieveConf = (RetrieveConf) msg;
          interpretFrom(retrieveConf.getFrom(), mMessageUri);
          timestamp = retrieveConf.getDate() * 1000L;
        } else {
          // Use constant string for outgoing messages
          mContact = mAddress = context.getString(R.string.messagelist_sender_self);
          timestamp = ((SendReq) msg).getDate() * 1000L;
        }

        String report = cursor.getString(columnsMap.mColumnMmsDeliveryReport);
        if ((report == null)
            || !mAddress.equals(context.getString(R.string.messagelist_sender_self))) {
          mDeliveryStatus = DeliveryStatus.NONE;
        } else {
          int reportInt;
          try {
            reportInt = Integer.parseInt(report);
            if (reportInt == PduHeaders.VALUE_YES) {
              mDeliveryStatus = DeliveryStatus.INFO;
            } else {
              mDeliveryStatus = DeliveryStatus.NONE;
            }
          } catch (NumberFormatException nfe) {
            Log.e(TAG, "Value for delivery report was invalid.");
            mDeliveryStatus = DeliveryStatus.NONE;
          }
        }

        report = cursor.getString(columnsMap.mColumnMmsReadReport);
        if ((report == null)
            || !mAddress.equals(context.getString(R.string.messagelist_sender_self))) {
          mReadReport = false;
        } else {
          int reportInt;
          try {
            reportInt = Integer.parseInt(report);
            mReadReport = (reportInt == PduHeaders.VALUE_YES);
          } catch (NumberFormatException nfe) {
            Log.e(TAG, "Value for read report was invalid.");
            mReadReport = false;
          }
        }

        SlideModel slide = mSlideshow.get(0);
        if ((slide != null) && slide.hasText()) {
          TextModel tm = slide.getText();
          if (tm.isDrmProtected()) {
            mBody = mContext.getString(R.string.drm_protected_text);
          } else {
            mBody = tm.getText();
          }
        }

        mMessageSize = mSlideshow.getCurrentMessageSize();
      }

      if (!isOutgoingMessage()) {
        mTimestamp =
            context.getString(
                getTimestampStrId(), MessageUtils.formatTimeStampString(context, timestamp));
      }
    } else {
      throw new MmsException("Unknown type of the message: " + type);
    }
  }