@Nullable
 public static ParcelableLocation fromLocation(@Nullable Location location) {
   if (location == null) return null;
   final ParcelableLocation result = new ParcelableLocation();
   result.latitude = location.getLatitude();
   result.longitude = location.getLongitude();
   return result;
 }
  private List<SingleResponse<ParcelableStatus>> updateStatus(
      final Builder builder, final ParcelableStatusUpdate statusUpdate) {
    final ArrayList<ContentValues> hashTagValues = new ArrayList<>();
    final Collection<String> hashTags = extractor.extractHashtags(statusUpdate.text);
    for (final String hashTag : hashTags) {
      final ContentValues values = new ContentValues();
      values.put(CachedHashtags.NAME, hashTag);
      hashTagValues.add(values);
    }
    final boolean hasEasterEggTriggerText = statusUpdate.text.contains(EASTER_EGG_TRIGGER_TEXT);
    final boolean hasEasterEggRestoreText =
        statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART1)
            && statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART2)
            && statusUpdate.text.contains(EASTER_EGG_RESTORE_TEXT_PART3);
    boolean mentionedHondaJOJO = false, notReplyToOther = false;
    mResolver.bulkInsert(
        CachedHashtags.CONTENT_URI, hashTagValues.toArray(new ContentValues[hashTagValues.size()]));

    final List<SingleResponse<ParcelableStatus>> results = new ArrayList<>();

    if (statusUpdate.accounts.length == 0) return Collections.emptyList();

    try {
      if (mUseUploader && mUploader == null) throw new UploaderNotFoundException(this);
      if (mUseShortener && mShortener == null) throw new ShortenerNotFoundException(this);

      final boolean hasMedia = statusUpdate.media != null && statusUpdate.media.length > 0;

      final String overrideStatusText;
      if (mUseUploader && mUploader != null && hasMedia) {
        final MediaUploadResult uploadResult;
        try {
          mUploader.waitForService();
          uploadResult =
              mUploader.upload(
                  statusUpdate, UploaderMediaItem.getFromStatusUpdate(this, statusUpdate));
        } catch (final Exception e) {
          throw new UploadException(this);
        } finally {
          mUploader.unbindService();
        }
        if (mUseUploader && hasMedia && uploadResult == null) throw new UploadException(this);
        if (uploadResult.error_code != 0) throw new UploadException(uploadResult.error_message);
        overrideStatusText = getImageUploadStatus(this, uploadResult.media_uris, statusUpdate.text);
      } else {
        overrideStatusText = null;
      }

      final String unShortenedText =
          isEmpty(overrideStatusText) ? statusUpdate.text : overrideStatusText;

      final boolean shouldShorten =
          mValidator.getTweetLength(unShortenedText) > mValidator.getMaxTweetLength();
      final String shortenedText;
      if (shouldShorten) {
        if (mUseShortener) {
          final StatusShortenResult shortenedResult;
          mShortener.waitForService();
          try {
            shortenedResult = mShortener.shorten(statusUpdate, unShortenedText);
          } catch (final Exception e) {
            throw new ShortenException(this);
          } finally {
            mShortener.unbindService();
          }
          if (shortenedResult == null || shortenedResult.shortened == null)
            throw new ShortenException(this);
          shortenedText = shortenedResult.shortened;
        } else throw new StatusTooLongException(this);
      } else {
        shortenedText = unShortenedText;
      }
      if (statusUpdate.media != null) {
        for (final ParcelableMediaUpdate media : statusUpdate.media) {
          final String path = getImagePathFromUri(this, Uri.parse(media.uri));
          final File file = path != null ? new File(path) : null;
          if (!mUseUploader && file != null && file.exists()) {
            BitmapUtils.downscaleImageIfNeeded(file, 95);
          }
        }
      }
      for (final ParcelableAccount account : statusUpdate.accounts) {
        final Twitter twitter =
            TwitterAPIFactory.getTwitterInstance(this, account.account_id, true, true);
        final TwitterUpload upload =
            TwitterAPIFactory.getTwitterInstance(
                this, account.account_id, true, true, TwitterUpload.class);
        final StatusUpdate status = new StatusUpdate(shortenedText);
        status.inReplyToStatusId(statusUpdate.in_reply_to_status_id);
        if (statusUpdate.location != null) {
          status.location(ParcelableLocation.toGeoLocation(statusUpdate.location));
        }
        if (!mUseUploader && hasMedia) {
          final BitmapFactory.Options o = new BitmapFactory.Options();
          o.inJustDecodeBounds = true;
          final long[] mediaIds = new long[statusUpdate.media.length];
          ContentLengthInputStream is = null;
          try {
            for (int i = 0, j = mediaIds.length; i < j; i++) {
              final ParcelableMediaUpdate media = statusUpdate.media[i];
              final String path = getImagePathFromUri(this, Uri.parse(media.uri));
              if (path == null) throw new FileNotFoundException();
              BitmapFactory.decodeFile(path, o);
              final File file = new File(path);
              is = new ContentLengthInputStream(file);
              is.setReadListener(
                  new StatusMediaUploadListener(this, mNotificationManager, builder, statusUpdate));
              final ContentType contentType;
              if (TextUtils.isEmpty(o.outMimeType)) {
                contentType = ContentType.parse("image/*");
              } else {
                contentType = ContentType.parse(o.outMimeType);
              }
              final MediaUploadResponse uploadResp =
                  upload.uploadMedia(
                      new FileTypedData(is, file.getName(), file.length(), contentType));
              mediaIds[i] = uploadResp.getId();
            }
          } catch (final FileNotFoundException e) {
            Log.w(LOGTAG, e);
          } catch (final TwitterException e) {
            final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
            results.add(response);
            continue;
          } finally {
            IoUtils.closeSilently(is);
          }
          status.mediaIds(mediaIds);
        }
        status.possiblySensitive(statusUpdate.is_possibly_sensitive);

        if (twitter == null) {
          results.add(SingleResponse.<ParcelableStatus>getInstance(new NullPointerException()));
          continue;
        }
        try {
          final Status resultStatus = twitter.updateStatus(status);
          if (!mentionedHondaJOJO) {
            final UserMentionEntity[] entities = resultStatus.getUserMentionEntities();
            if (entities == null || entities.length == 0) {
              mentionedHondaJOJO = statusUpdate.text.contains("@" + HONDAJOJO_SCREEN_NAME);
            } else if (entities.length == 1 && entities[0].getId() == HONDAJOJO_ID) {
              mentionedHondaJOJO = true;
            }
            Utils.setLastSeen(this, entities, System.currentTimeMillis());
          }
          if (!notReplyToOther) {
            final long inReplyToUserId = resultStatus.getInReplyToUserId();
            if (inReplyToUserId <= 0 || inReplyToUserId == HONDAJOJO_ID) {
              notReplyToOther = true;
            }
          }
          final ParcelableStatus result =
              new ParcelableStatus(resultStatus, account.account_id, false);
          results.add(SingleResponse.getInstance(result));
        } catch (final TwitterException e) {
          final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
          results.add(response);
        }
      }
    } catch (final UpdateStatusException e) {
      final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(e);
      results.add(response);
    }
    if (mentionedHondaJOJO) {
      triggerEasterEgg(notReplyToOther, hasEasterEggTriggerText, hasEasterEggRestoreText);
    }
    return results;
  }
  public ParcelableStatus(final Status orig, final long account_id, final boolean is_gap) {
    this.is_gap = is_gap;
    this.account_id = account_id;
    id = orig.getId();
    timestamp = getTime(orig.getCreatedAt());

    final Status retweeted = orig.getRetweetedStatus();
    final User retweet_user = retweeted != null ? orig.getUser() : null;
    is_retweet = orig.isRetweet();
    retweet_id = retweeted != null ? retweeted.getId() : -1;
    retweet_timestamp = retweeted != null ? getTime(retweeted.getCreatedAt()) : -1;
    retweeted_by_user_id = retweet_user != null ? retweet_user.getId() : -1;
    retweeted_by_user_name = retweet_user != null ? retweet_user.getName() : null;
    retweeted_by_user_screen_name = retweet_user != null ? retweet_user.getScreenName() : null;
    retweeted_by_user_profile_image = TwitterContentUtils.getProfileImageUrl(retweet_user);

    final Status quoted = orig.getQuotedStatus();
    final User quote_user = quoted != null ? orig.getUser() : null;
    is_quote = orig.isQuote();
    quote_id = quoted != null ? quoted.getId() : -1;
    quote_text_html = TwitterContentUtils.formatStatusText(orig);
    quote_text_plain = TwitterContentUtils.unescapeTwitterStatusText(orig.getText());
    quote_text_unescaped = HtmlEscapeHelper.toPlainText(quote_text_html);
    quote_timestamp = orig.getCreatedAt().getTime();
    quote_source = orig.getSource();
    quote_retweet_count = orig.getRetweetCount();
    quote_favorite_count = orig.getFavoriteCount();
    quote_reply_count = orig.getReplyCount();

    quoted_by_user_id = quote_user != null ? quote_user.getId() : -1;
    quoted_by_user_name = quote_user != null ? quote_user.getName() : null;
    quoted_by_user_screen_name = quote_user != null ? quote_user.getScreenName() : null;
    quoted_by_user_profile_image = TwitterContentUtils.getProfileImageUrl(quote_user);
    quoted_by_user_is_protected = quote_user != null && quote_user.isProtected();
    quoted_by_user_is_verified = quote_user != null && quote_user.isVerified();

    final Status status;
    if (quoted != null) {
      status = quoted;
    } else if (retweeted != null) {
      status = retweeted;
    } else {
      status = orig;
    }
    final User user = status.getUser();
    user_id = user.getId();
    user_name = user.getName();
    user_screen_name = user.getScreenName();
    user_profile_image_url = TwitterContentUtils.getProfileImageUrl(user);
    user_is_protected = user.isProtected();
    user_is_verified = user.isVerified();
    user_is_following = user.isFollowing();
    text_html = TwitterContentUtils.formatStatusText(status);
    media = ParcelableMedia.fromStatus(status);
    quote_media = quoted != null ? ParcelableMedia.fromStatus(orig) : null;
    text_plain = TwitterContentUtils.unescapeTwitterStatusText(status.getText());
    retweet_count = status.getRetweetCount();
    favorite_count = status.getFavoriteCount();
    reply_count = status.getReplyCount();
    in_reply_to_name = TwitterContentUtils.getInReplyToName(retweeted != null ? retweeted : orig);
    in_reply_to_screen_name = (retweeted != null ? retweeted : orig).getInReplyToScreenName();
    in_reply_to_status_id = (retweeted != null ? retweeted : orig).getInReplyToStatusId();
    in_reply_to_user_id = (retweeted != null ? retweeted : orig).getInReplyToUserId();
    source = status.getSource();
    location = ParcelableLocation.fromGeoLocation(status.getGeoLocation());
    is_favorite = status.isFavorited();
    text_unescaped = HtmlEscapeHelper.toPlainText(text_html);
    my_retweet_id = retweeted_by_user_id == account_id ? id : status.getCurrentUserRetweet();
    is_possibly_sensitive = status.isPossiblySensitive();
    mentions = ParcelableUserMention.fromUserMentionEntities(status.getUserMentionEntities());
    card = ParcelableCardEntity.fromCardEntity(status.getCard(), account_id);
    place_full_name = getPlaceFullName(status.getPlace());
    card_name = card != null ? card.name : null;
  }
 public static GeoLocation toGeoLocation(final ParcelableLocation location) {
   return isValidLocation(location) ? location.toGeoLocation() : null;
 }
 public static boolean isValidLocation(final ParcelableLocation location) {
   return location != null && location.isValid();
 }
 public static ParcelableLocation fromString(final String string) {
   final ParcelableLocation location = new ParcelableLocation(string);
   if (ParcelableLocation.isValidLocation(location)) return location;
   return null;
 }