protected void onPostExecute(CommentList comments) {
      mIsUpdatingComments = false;
      mUpdateCommentsTask = null;
      if (!hasActivity()) {
        return;
      }
      if (isLoadingMore) {
        hideLoadingProgress();
      }
      mPullToRefreshHelper.setRefreshing(false);

      if (isCancelled()) return;

      mCanLoadMoreComments = (comments != null && comments.size() > 0);

      // result will be null on error OR if no more comments exists
      if (comments == null) {
        if (isError && !getActivity().isFinishing()) {
          ToastUtils.showToast(getActivity(), getString(R.string.error_refresh_comments));
        }
        return;
      }

      if (comments.size() > 0) {
        getCommentAdapter().loadComments();
      }
    }
  private void moderateSelectedComments(final CommentStatus newStatus) {
    final CommentList selectedComments = getCommentAdapter().getSelectedComments();
    final CommentList updateComments = new CommentList();

    // build list of comments whose status is different than passed
    for (Comment comment : selectedComments) {
      if (comment.getStatusEnum() != newStatus) updateComments.add(comment);
    }
    if (updateComments.size() == 0) return;

    if (!NetworkUtils.checkConnection(getActivity())) return;

    final int dlgId;
    switch (newStatus) {
      case APPROVED:
        dlgId = CommentDialogs.ID_COMMENT_DLG_APPROVING;
        break;
      case UNAPPROVED:
        dlgId = CommentDialogs.ID_COMMENT_DLG_UNAPPROVING;
        break;
      case SPAM:
        dlgId = CommentDialogs.ID_COMMENT_DLG_SPAMMING;
        break;
      case TRASH:
        dlgId = CommentDialogs.ID_COMMENT_DLG_TRASHING;
        break;
      default:
        return;
    }
    getActivity().showDialog(dlgId);

    CommentActions.OnCommentsModeratedListener listener =
        new CommentActions.OnCommentsModeratedListener() {
          @Override
          public void onCommentsModerated(final CommentList moderatedComments) {
            if (!hasActivity()) return;
            finishActionMode();
            dismissDialog(dlgId);
            if (moderatedComments.size() > 0) {
              getCommentAdapter().clearSelectedComments();
              getCommentAdapter().replaceComments(moderatedComments);
              if (mOnCommentChangeListener != null) {
                ChangeType changeType =
                    (newStatus == CommentStatus.TRASH ? ChangeType.TRASHED : ChangeType.STATUS);
                mOnCommentChangeListener.onCommentChanged(ChangedFrom.COMMENT_LIST, changeType);
              }
            } else {
              ToastUtils.showToast(getActivity(), R.string.error_moderate_comment);
            }
          }
        };

    CommentActions.moderateComments(
        WordPress.getCurrentLocalTableBlogId(), updateComments, newStatus, listener);
  }
  /** delete multiple comments */
  private static void deleteComments(
      final int accountId,
      final CommentList comments,
      final OnCommentsModeratedListener actionListener) {

    final Blog blog = WordPress.getBlog(accountId);

    if (blog == null || comments == null || comments.size() == 0) {
      if (actionListener != null) actionListener.onCommentsModerated(new CommentList());
      return;
    }

    final CommentList deletedComments = new CommentList();
    final int localBlogId = blog.getLocalTableBlogId();
    final int remoteBlogId = blog.getRemoteBlogId();

    final Handler handler = new Handler();
    new Thread() {
      @Override
      public void run() {
        XMLRPCClientInterface client =
            XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword());

        for (Comment comment : comments) {
          Object[] params = {
            remoteBlogId, blog.getUsername(), blog.getPassword(), comment.commentID
          };

          Object result;
          try {
            result = client.call("wp.deleteComment", params);
            boolean success = (result != null && Boolean.parseBoolean(result.toString()));
            if (success) deletedComments.add(comment);
          } catch (XMLRPCException e) {
            AppLog.e(T.COMMENTS, "Error while deleting comment", e);
          } catch (IOException e) {
            AppLog.e(T.COMMENTS, "Error while deleting comment", e);
          } catch (XmlPullParserException e) {
            AppLog.e(T.COMMENTS, "Error while deleting comment", e);
          }
        }

        // remove successfully deleted comments from SQLite
        CommentTable.deleteComments(localBlogId, deletedComments);

        if (actionListener != null) {
          handler.post(
              new Runnable() {
                @Override
                public void run() {
                  actionListener.onCommentsModerated(deletedComments);
                }
              });
        }
      }
    }.start();
  }
    @Override
    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
      final CommentList selectedComments = getCommentAdapter().getSelectedComments();

      boolean hasSelection = (selectedComments.size() > 0);
      boolean hasApproved =
          hasSelection && selectedComments.hasAnyWithStatus(CommentStatus.APPROVED);
      boolean hasUnapproved =
          hasSelection && selectedComments.hasAnyWithStatus(CommentStatus.UNAPPROVED);
      boolean hasSpam = hasSelection && selectedComments.hasAnyWithStatus(CommentStatus.SPAM);
      boolean hasAnyNonSpam =
          hasSelection && selectedComments.hasAnyWithoutStatus(CommentStatus.SPAM);

      setItemEnabled(menu, R.id.menu_approve, hasUnapproved || hasSpam);
      setItemEnabled(menu, R.id.menu_unapprove, hasApproved);
      setItemEnabled(menu, R.id.menu_spam, hasAnyNonSpam);
      setItemEnabled(menu, R.id.menu_trash, hasSelection);

      return true;
    }
  /**
   * change the status of multiple comments TODO: investigate using system.multiCall to perform a
   * single call to moderate the list
   */
  static void moderateComments(
      final int accountId,
      final CommentList comments,
      final CommentStatus newStatus,
      final OnCommentsModeratedListener actionListener) {

    // deletion is handled separately
    if (newStatus != null && newStatus.equals(CommentStatus.TRASH)) {
      deleteComments(accountId, comments, actionListener);
      return;
    }

    final Blog blog = WordPress.getBlog(accountId);

    if (blog == null
        || comments == null
        || comments.size() == 0
        || newStatus == null
        || newStatus == CommentStatus.UNKNOWN) {
      if (actionListener != null) actionListener.onCommentsModerated(new CommentList());
      return;
    }

    final CommentList moderatedComments = new CommentList();
    final String newStatusStr = CommentStatus.toString(newStatus);
    final int localBlogId = blog.getLocalTableBlogId();
    final int remoteBlogId = blog.getRemoteBlogId();

    final Handler handler = new Handler();
    new Thread() {
      @Override
      public void run() {
        XMLRPCClientInterface client =
            XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword());
        for (Comment comment : comments) {
          Map<String, String> postHash = new HashMap<String, String>();
          postHash.put("status", newStatusStr);
          postHash.put("content", comment.getCommentText());
          postHash.put("author", comment.getAuthorName());
          postHash.put("author_url", comment.getAuthorUrl());
          postHash.put("author_email", comment.getAuthorEmail());

          Object[] params = {
            remoteBlogId,
            blog.getUsername(),
            blog.getPassword(),
            Long.toString(comment.commentID),
            postHash
          };

          Object result;
          try {
            result = client.call("wp.editComment", params);
            boolean success = (result != null && Boolean.parseBoolean(result.toString()));
            if (success) {
              comment.setStatus(newStatusStr);
              moderatedComments.add(comment);
            }
          } catch (XMLRPCException e) {
            AppLog.e(T.COMMENTS, "Error while editing comment", e);
          } catch (IOException e) {
            AppLog.e(T.COMMENTS, "Error while editing comment", e);
          } catch (XmlPullParserException e) {
            AppLog.e(T.COMMENTS, "Error while editing comment", e);
          }
        }

        // update status in SQLite of successfully moderated comments
        CommentTable.updateCommentsStatus(localBlogId, moderatedComments, newStatusStr);

        if (actionListener != null) {
          handler.post(
              new Runnable() {
                @Override
                public void run() {
                  actionListener.onCommentsModerated(moderatedComments);
                }
              });
        }
      }
    }.start();
  }