package kr.kdev.dg1s.biowiki.ui.comments;
import android.os.Handler;
import android.text.TextUtils;
import com.android.volley.VolleyError;
import com.wordpress.rest.RestRequest;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlrpc.android.XMLRPCClientInterface;
import org.xmlrpc.android.XMLRPCException;
import org.xmlrpc.android.XMLRPCFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import kr.kdev.dg1s.biowiki.BioWiki;
import kr.kdev.dg1s.biowiki.datasets.CommentTable;
import kr.kdev.dg1s.biowiki.models.Blog;
import kr.kdev.dg1s.biowiki.models.Comment;
import kr.kdev.dg1s.biowiki.models.CommentList;
import kr.kdev.dg1s.biowiki.models.CommentStatus;
import kr.kdev.dg1s.biowiki.models.Note;
import kr.kdev.dg1s.biowiki.util.AppLog;
/**
* Created by nbradbury on 11/8/13.
* actions related to comments - replies, moderating, etc.
* methods below do network calls in the background & update local DB upon success
* all methods below MUST be called from UI thread
*/
public class CommentActions {
private CommentActions() {
throw new AssertionError();
}
/*
* add a comment for the passed post
*/
public static void addComment(final int accountId,
final String postID,
final String commentText,
final CommentActionListener actionListener) {
final Blog blog = BioWiki.getBlog(accountId);
if (blog == null || TextUtils.isEmpty(commentText)) {
if (actionListener != null)
actionListener.onActionResult(false);
return;
}
final Handler handler = new Handler();
new Thread() {
@Override
public void run() {
XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(),
blog.getHttppassword());
Map<String, Object> commentHash = new HashMap<String, Object>();
commentHash.put("content", commentText);
commentHash.put("author", "");
commentHash.put("author_url", "");
commentHash.put("author_email", "");
Object[] params = {
blog.getRemoteBlogId(),
blog.getUsername(),
blog.getPassword(),
postID,
commentHash};
int newCommentID;
try {
newCommentID = (Integer) client.call("wp.newComment", params);
} catch (XMLRPCException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e);
newCommentID = -1;
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e);
newCommentID = -1;
} catch (XmlPullParserException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e);
newCommentID = -1;
}
final boolean succeeded = (newCommentID >= 0);
if (actionListener != null) {
handler.post(new Runnable() {
@Override
public void run() {
actionListener.onActionResult(succeeded);
}
});
}
}
}.start();
}
/**
* reply to an individual comment
*/
static void submitReplyToComment(final int accountId,
final Comment comment,
final String replyText,
final CommentActionListener actionListener) {
final Blog blog = BioWiki.getBlog(accountId);
if (blog == null || comment == null || TextUtils.isEmpty(replyText)) {
if (actionListener != null)
actionListener.onActionResult(false);
return;
}
final Handler handler = new Handler();
new Thread() {
@Override
public void run() {
XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(),
blog.getHttppassword());
Map<String, Object> replyHash = new HashMap<String, Object>();
replyHash.put("comment_parent", Long.toString(comment.commentID));
replyHash.put("content", replyText);
replyHash.put("author", "");
replyHash.put("author_url", "");
replyHash.put("author_email", "");
Object[] params = {
blog.getRemoteBlogId(),
blog.getUsername(),
blog.getPassword(),
Long.toString(comment.postID),
replyHash};
long newCommentID;
try {
Object newCommentIDObject = client.call("wp.newComment", params);
if (newCommentIDObject instanceof Integer) {
newCommentID = ((Integer) newCommentIDObject).longValue();
} else if (newCommentIDObject instanceof Long) {
newCommentID = (Long) newCommentIDObject;
} else {
AppLog.e(AppLog.T.COMMENTS, "wp.newComment returned the wrong data type");
newCommentID = -1;
}
} catch (XMLRPCException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e);
newCommentID = -1;
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e);
newCommentID = -1;
} catch (XmlPullParserException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e);
newCommentID = -1;
}
final boolean succeeded = (newCommentID >= 0);
if (actionListener != null) {
handler.post(new Runnable() {
@Override
public void run() {
actionListener.onActionResult(succeeded);
}
});
}
}
}.start();
}
/**
* reply to an individual comment that came from a notification - this differs from
* submitReplyToComment() in that it enables responding to a reply to a comment this
* user made on someone else's blog
*/
static void submitReplyToCommentNote(final Note note,
final String replyText,
final CommentActionListener actionListener) {
if (note == null || TextUtils.isEmpty(replyText)) {
if (actionListener != null)
actionListener.onActionResult(false);
return;
}
RestRequest.Listener listener = new RestRequest.Listener() {
@Override
public void onResponse(JSONObject jsonObject) {
if (actionListener != null)
actionListener.onActionResult(true);
}
};
RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
if (volleyError != null)
AppLog.e(AppLog.T.COMMENTS, volleyError.getMessage(), volleyError);
if (actionListener != null)
actionListener.onActionResult(false);
}
};
Note.Reply reply = note.buildReply(replyText);
BioWiki.getRestClientUtils().replyToComment(reply, listener, errorListener);
}
/**
* change the status of a single comment
*/
static void moderateComment(final int accountId,
final Comment comment,
final CommentStatus newStatus,
final CommentActionListener actionListener) {
// deletion is handled separately
if (newStatus != null && newStatus.equals(CommentStatus.TRASH)) {
deleteComment(accountId, comment, actionListener);
return;
}
final Blog blog = BioWiki.getBlog(accountId);
if (blog == null || comment == null || newStatus == null || newStatus == CommentStatus.UNKNOWN) {
if (actionListener != null)
actionListener.onActionResult(false);
return;
}
final Handler handler = new Handler();
new Thread() {
@Override
public void run() {
XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(),
blog.getHttppassword());
Map<String, String> postHash = new HashMap<String, String>();
postHash.put("status", CommentStatus.toString(newStatus));
postHash.put("content", comment.getCommentText());
postHash.put("author", comment.getAuthorName());
postHash.put("author_url", comment.getAuthorUrl());
postHash.put("author_email", comment.getAuthorEmail());
Object[] params = {blog.getRemoteBlogId(),
blog.getUsername(),
blog.getPassword(),
Long.toString(comment.commentID),
postHash};
Object result;
try {
result = client.call("wp.editComment", params);
} catch (XMLRPCException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e);
result = null;
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e);
result = null;
} catch (XmlPullParserException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e);
result = null;
}
final boolean success = (result != null && Boolean.parseBoolean(result.toString()));
if (success)
CommentTable.updateCommentStatus(blog.getLocalTableBlogId(), comment.commentID, CommentStatus.toString(newStatus));
if (actionListener != null) {
handler.post(new Runnable() {
@Override
public void run() {
actionListener.onActionResult(success);
}
});
}
}
}.start();
}
/**
* 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 = BioWiki.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(AppLog.T.COMMENTS, "Error while editing comment", e);
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e);
} catch (XmlPullParserException e) {
AppLog.e(AppLog.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();
}
/**
* delete (trash) a single comment
*/
private static void deleteComment(final int accountId,
final Comment comment,
final CommentActionListener actionListener) {
final Blog blog = BioWiki.getBlog(accountId);
if (blog == null || comment == null) {
if (actionListener != null)
actionListener.onActionResult(false);
return;
}
final Handler handler = new Handler();
new Thread() {
@Override
public void run() {
XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(),
blog.getHttppassword());
Object[] params = {
blog.getRemoteBlogId(),
blog.getUsername(),
blog.getPassword(),
comment.commentID};
Object result;
try {
result = client.call("wp.deleteComment", params);
} catch (final XMLRPCException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e);
result = null;
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e);
result = null;
} catch (XmlPullParserException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e);
result = null;
}
final boolean success = (result != null && Boolean.parseBoolean(result.toString()));
if (success)
CommentTable.deleteComment(accountId, comment.commentID);
if (actionListener != null) {
handler.post(new Runnable() {
@Override
public void run() {
actionListener.onActionResult(success);
}
});
}
}
}.start();
}
/**
* delete multiple comments
*/
private static void deleteComments(final int accountId,
final CommentList comments,
final OnCommentsModeratedListener actionListener) {
final Blog blog = BioWiki.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(AppLog.T.COMMENTS, "Error while deleting comment", e);
} catch (IOException e) {
AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e);
} catch (XmlPullParserException e) {
AppLog.e(AppLog.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();
}
/*
* used by comment fragments to alert container activity of a change to one or more
* comments (moderated, deleted, added, etc.)
*/
public static enum ChangedFrom {
COMMENT_LIST, COMMENT_DETAIL
}
public static enum ChangeType {EDITED, STATUS, REPLIED, TRASHED}
/*
* listener when a comment action is performed
*/
public interface CommentActionListener {
public void onActionResult(boolean succeeded);
}
/*
* listener when comments are moderated or deleted
*/
public interface OnCommentsModeratedListener {
public void onCommentsModerated(final CommentList moderatedComments);
}
public static interface OnCommentChangeListener {
public void onCommentChanged(ChangedFrom changedFrom, ChangeType changeType);
}
}