private Tweet getTweetObjectFromStatus(Status status) {

    Tweet tweet = new Tweet();
    tweet.setId(Long.toString(status.getId()));
    tweet.setText(status.getText());
    tweet.setCreatedAt(status.getCreatedAt());

    tweet.setFavCount(status.getFavoriteCount());

    User user = status.getUser();

    tweet.setUserId(user.getId());
    tweet.setUserName(user.getName());
    tweet.setUserScreenName(user.getScreenName());

    HashtagEntity[] hashtagEntities = status.getHashtagEntities();
    List<String> hashtags = new ArrayList<String>();

    for (HashtagEntity hashtagEntity : hashtagEntities) {
      hashtags.add(hashtagEntity.getText());
    }

    tweet.setHashTags(hashtags.toArray(new String[hashtags.size()]));

    GeoLocation geoLocation = status.getGeoLocation();
    if (geoLocation != null) {
      double[] coordinates = {geoLocation.getLongitude(), geoLocation.getLatitude()};
      tweet.setCoordinates(coordinates);
    }

    return tweet;
  }
  private static Record buildEntities(Schema schemaEntities, Status status) {
    GenericRecordBuilder builderEntities = new GenericRecordBuilder(schemaEntities);

    if (status.getHashtagEntities().length > 0) {
      Schema schemaHashtagObject = schemaEntities.getField("hashtags").schema().getElementType();
      List<GenericRecord> listHashtagObjects = new ArrayList<>();
      for (HashtagEntity hashtagEntity : status.getHashtagEntities()) {
        GenericRecordBuilder builderHashtagObject = new GenericRecordBuilder(schemaHashtagObject);
        builderHashtagObject.set("text", hashtagEntity.getText());
        builderHashtagObject.set("start", hashtagEntity.getStart());
        builderHashtagObject.set("end", hashtagEntity.getEnd());
        listHashtagObjects.add(builderHashtagObject.build());
      }
      builderEntities.set("hashtags", listHashtagObjects);
    } else builderEntities.set("hashtags", Collections.emptyList());

    if (status.getSymbolEntities().length > 0) {
      Schema schemaSymbolObject = schemaEntities.getField("symbols").schema().getElementType();
      List<GenericRecord> listSymbolObject = new ArrayList<>();
      for (SymbolEntity symbolEntity : status.getSymbolEntities()) {
        GenericRecordBuilder builderSymbolObject = new GenericRecordBuilder(schemaSymbolObject);
        builderSymbolObject.set("text", symbolEntity.getText());
        builderSymbolObject.set("start", symbolEntity.getStart());
        builderSymbolObject.set("end", symbolEntity.getEnd());
        listSymbolObject.add(builderSymbolObject.build());
      }
      builderEntities.set("symbols", listSymbolObject);
    } else builderEntities.set("symbols", Collections.emptyList());

    if (status.getMediaEntities().length > 0) {
      Schema schemaMediaObject = schemaEntities.getField("media").schema().getElementType();
      List<GenericRecord> listMediaObject = new ArrayList<>();
      for (MediaEntity mediaEntity : status.getMediaEntities()) {
        GenericRecordBuilder builderMediaObject = new GenericRecordBuilder(schemaMediaObject);
        builderMediaObject.set("url", mediaEntity.getURL());
        builderMediaObject.set("display_url", mediaEntity.getDisplayURL());
        builderMediaObject.set("expanded_url", mediaEntity.getExpandedURL());
        builderMediaObject.set("id", mediaEntity.getId());
        builderMediaObject.set("media_url", mediaEntity.getMediaURL());
        builderMediaObject.set("media_url_https", mediaEntity.getMediaURLHttps());
        builderMediaObject.set("type", mediaEntity.getType());
        builderMediaObject.set("text", mediaEntity.getText());
        builderMediaObject.set("start", mediaEntity.getStart());
        builderMediaObject.set("end", mediaEntity.getEnd());

        Schema schemaSize = schemaMediaObject.getField("sizes").schema().getValueType();
        GenericRecordBuilder builderSize = new GenericRecordBuilder(schemaSize);
        Map<String, GenericRecord> mapSizes = new HashMap<>(4);
        for (int key : mediaEntity.getSizes().keySet()) {
          Size size = mediaEntity.getSizes().get(key);
          builderSize.set("h", size.getHeight());
          builderSize.set("w", size.getWidth());
          builderSize.set("resize", size.getResize());
          mapSizes.put(Integer.toString(key), builderSize.build());
        }
        builderMediaObject.set("sizes", mapSizes);
        listMediaObject.add(builderMediaObject.build());
      }
      builderEntities.set("media", listMediaObject);
    } else builderEntities.set("media", Collections.emptyList());

    if (status.getURLEntities().length > 0) {
      Schema schemaURLObject = schemaEntities.getField("urls").schema().getElementType();
      List<GenericRecord> listURLObject1 = new ArrayList<>();
      for (URLEntity urlEntity : status.getURLEntities())
        listURLObject1.add(buildURLEntity(schemaURLObject, urlEntity));
      builderEntities.set("urls", listURLObject1);
    } else builderEntities.set("urls", Collections.emptyList());

    if (status.getUserMentionEntities().length > 0) {
      Schema schemaUserMentionObject =
          schemaEntities.getField("user_mentions").schema().getElementType();
      List<GenericRecord> listUserMentionObject = new ArrayList<>();
      for (UserMentionEntity userMentionEntity : status.getUserMentionEntities()) {
        GenericRecordBuilder builderUserMentionObject =
            new GenericRecordBuilder(schemaUserMentionObject);
        builderUserMentionObject.set("name", userMentionEntity.getName());
        builderUserMentionObject.set("screen_name", userMentionEntity.getScreenName());
        builderUserMentionObject.set("text", userMentionEntity.getText());
        builderUserMentionObject.set("id", userMentionEntity.getId());
        builderUserMentionObject.set("start", userMentionEntity.getStart());
        builderUserMentionObject.set("end", userMentionEntity.getEnd());
        listUserMentionObject.add(builderUserMentionObject.build());
      }
      builderEntities.set("user_mentions", listUserMentionObject);
    } else builderEntities.set("user_mentions", Collections.emptyList());

    if (status.getExtendedMediaEntities().length > 0) {
      Schema schemaExtendedMediaObject =
          schemaEntities.getField("extended_entities").schema().getElementType();
      List<GenericRecord> listExtendedMediaObject = new ArrayList<>();
      for (ExtendedMediaEntity extendedMediaEntity : status.getExtendedMediaEntities()) {
        GenericRecordBuilder builderExtendedMediaObject =
            new GenericRecordBuilder(schemaExtendedMediaObject);
        builderExtendedMediaObject.set("url", extendedMediaEntity.getURL());
        builderExtendedMediaObject.set("display_url", extendedMediaEntity.getDisplayURL());
        builderExtendedMediaObject.set("expanded_url", extendedMediaEntity.getExpandedURL());
        builderExtendedMediaObject.set("id", extendedMediaEntity.getId());
        builderExtendedMediaObject.set("media_url", extendedMediaEntity.getMediaURL());
        builderExtendedMediaObject.set("media_url_https", extendedMediaEntity.getMediaURLHttps());
        builderExtendedMediaObject.set("type", extendedMediaEntity.getType());
        builderExtendedMediaObject.set("text", extendedMediaEntity.getText());
        builderExtendedMediaObject.set("start", extendedMediaEntity.getStart());
        builderExtendedMediaObject.set("end", extendedMediaEntity.getEnd());

        Schema schemaSize = schemaExtendedMediaObject.getField("sizes").schema().getValueType();
        GenericRecordBuilder builderSize = new GenericRecordBuilder(schemaSize);
        Map<String, GenericRecord> mapSizes = new HashMap<>(4);
        for (int key : extendedMediaEntity.getSizes().keySet()) {
          Size size = extendedMediaEntity.getSizes().get(key);
          builderSize.set("h", size.getHeight());
          builderSize.set("w", size.getWidth());
          builderSize.set("resize", size.getResize());
          mapSizes.put(Integer.toString(key), builderSize.build());
        }
        builderExtendedMediaObject.set("sizes", mapSizes);

        Schema schemaVideoInfo = schemaExtendedMediaObject.getField("video_info").schema();
        GenericRecordBuilder builderVideoInfo = new GenericRecordBuilder(schemaVideoInfo);
        builderVideoInfo.set("h", extendedMediaEntity.getVideoAspectRatioHeight());
        builderVideoInfo.set("w", extendedMediaEntity.getVideoAspectRatioWidth());
        builderVideoInfo.set("duration_millis", extendedMediaEntity.getVideoDurationMillis());

        Schema schemaVideoVariants = schemaVideoInfo.getField("variants").schema().getElementType();
        List<GenericRecord> listVideoVariants = new ArrayList<>();
        for (Variant extendedVideoVariant : extendedMediaEntity.getVideoVariants()) {
          GenericRecordBuilder builderVideoVariant = new GenericRecordBuilder(schemaVideoVariants);
          builderVideoVariant.set("bitrate", extendedVideoVariant.getBitrate());
          builderVideoVariant.set("content_type", extendedVideoVariant.getContentType());
          builderVideoVariant.set("url", extendedVideoVariant.getUrl());
          listVideoVariants.add(builderVideoVariant.build());
        }
        builderVideoInfo.set("variants", listVideoVariants);
        builderExtendedMediaObject.set("video_info", builderVideoInfo.build());

        listExtendedMediaObject.add(builderExtendedMediaObject.build());
      }
      builderEntities.set("extended_entities", listExtendedMediaObject);
    } else builderEntities.set("extended_entities", Collections.emptyList());
    return builderEntities.build();
  }
  /**
   * Retrieve a list of statuses. Depending on listId, this is taken from different sources:
   *
   * <ul>
   *   <li>0 : home timeline
   *   <li>-1 : mentions
   *   <li>>0 : User list
   * </ul>
   *
   * This method may trigger a network call if fromDbOnly is false. The filter if not null is a
   * regular expression, that if matches filters the tweet.
   *
   * @param fromDbOnly If true only statuses already in the DB are returned
   * @param listId Id of the list / timeline to fetch (see above)
   * @param updateStatusList Should the currently displayed list be updated?
   * @return List of status items along with some counts
   */
  private MetaList<Status> getTimlinesFromTwitter(
      boolean fromDbOnly, int listId, boolean updateStatusList) {
    Paging paging = new Paging();

    MetaList<Status> myStatuses;

    long last = tdb.getLastRead(account.getId(), listId);
    if (last > 0) // && !Debug.isDebuggerConnected())
    paging.sinceId(last).setCount(200);
    else paging.setCount(50); // 50 Tweets if we don't have the timeline yet

    switch (listId) {
      case 0:
        // Home time line
        myStatuses = th.getTimeline(paging, listId, fromDbOnly);

        break;
      case -1:
        myStatuses = th.getTimeline(paging, listId, fromDbOnly);
        break;
      case -2:
        // see below at getDirectsFromTwitter
        myStatuses = new MetaList<Status>();
        break;
      case -3:
        myStatuses = th.getTimeline(paging, listId, fromDbOnly);
        break;
      case -4:
        myStatuses = th.getTimeline(paging, listId, fromDbOnly);
        break;
      default:
        myStatuses = th.getUserList(paging, listId, fromDbOnly, unreadCount);
        if (unreadCount > -1) {
          List<Status> list = myStatuses.getList();
          if (list.size() <= unreadCount) unreadCount = list.size() - 1;
          if (unreadCount > -1) last = list.get(unreadCount).getId();
        }

        break;
    }

    long newLast = -1;
    // Update the 'since' id in the database
    if (myStatuses.getList().size() > 0) {
      newLast =
          myStatuses
              .getList()
              .get(0)
              .getId(); // assumption is that twitter sends the newest (=highest id) first
      tdb.updateOrInsertLastRead(account.getId(), listId, newLast);
    }

    // Sync with TweetMarker
    long newLast2 = -1;
    if (listId >= 0 && !account.isStatusNet() && !fromDbOnly) {
      if (listId == 0)
        newLast2 = TweetMarkerSync.syncFromTweetMarker("timeline", account.getName());
      else newLast2 = TweetMarkerSync.syncFromTweetMarker("lists." + listId, account.getName());

      if (newLast2 > newLast) {
        tdb.updateOrInsertLastRead(account.getId(), listId, newLast2);
      } else {
        if (listId == 0)
          TweetMarkerSync.syncToTweetMarker("timeline", newLast, account.getName(), th.getOAuth());
        else
          TweetMarkerSync.syncToTweetMarker(
              "lists." + listId, newLast, account.getName(), th.getOAuth());
      }
    }

    MetaList<Status> metaList;
    if (updateStatusList) {
      statuses = new ArrayList<Status>();
      List<Status> data = new ArrayList<Status>(myStatuses.getList().size());
      if (filterPattern == null) {
        setupFilter(); // TODO report errors?
      }
      for (Status status : myStatuses.getList()) {
        boolean shouldFilter = matchesFilter(status);
        if (shouldFilter) {
          Log.i(
              "TweetListActivity::filter, filtered ",
              status.getUser().getScreenName() + " - " + status.getText());
        } else {
          data.add(status);
          statuses.add(status);
        }
      }
      metaList = new MetaList<Status>(data, myStatuses.getNumOriginal(), myStatuses.getNumAdded());
    } else {
      metaList = new MetaList<Status>(new ArrayList<Status>(), 0, 0);
    }

    if (newLast2 > last) {
      metaList.oldLast = newLast2;
      // the read status from remote is newer than the last read locally, so lets mark those in
      // between as read
      for (Status s : statuses) {
        long id = s.getId();
        if (id > last) {
          th.markStatusAsOld(id);
        }
      }
    } else {
      metaList.oldLast = last;
    }

    for (Status status : metaList.getList()) {
      AccountHolder accountHolder = AccountHolder.getInstance();
      accountHolder.addUserName(status.getUser().getScreenName());
      if (status.getHashtagEntities() != null) {
        for (HashtagEntity hte : status.getHashtagEntities()) {
          accountHolder.addHashTag(hte.getText());
        }
      }
    }

    return metaList;
  }