/* Copyright (C) 2013 Prasanna Thirumalai This file is part of StackX. StackX is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. StackX is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with StackX. If not, see <http://www.gnu.org/licenses/>. */ package com.prasanna.android.stacknetwork.service; import java.io.Serializable; import java.util.ArrayList; import android.content.Intent; import android.os.Bundle; import android.os.ResultReceiver; import com.prasanna.android.http.AbstractHttpException; import com.prasanna.android.stacknetwork.model.Answer; import com.prasanna.android.stacknetwork.model.Comment; import com.prasanna.android.stacknetwork.model.Post.PostType; import com.prasanna.android.stacknetwork.model.Question; import com.prasanna.android.stacknetwork.model.StackXPage; import com.prasanna.android.stacknetwork.utils.QuestionsCache; import com.prasanna.android.stacknetwork.utils.StringConstants; import com.prasanna.android.utils.LogWrapper; public class QuestionDetailsIntentService extends AbstractIntentService { private static final String TAG = QuestionDetailsIntentService.class.getSimpleName(); private QuestionServiceHelper questionService = QuestionServiceHelper.getInstance(); public static final int RESULT_CODE_Q = 0x01; public static final int RESULT_CODE_Q_BODY = 0x02; public static final int RESULT_CODE_Q_COMMENTS = 0x03; public static final int RESULT_CODE_ANSWERS = 0x04; public static final int RESULT_CODE_Q_CACHED = 0x05; public static final int RESULT_CODE_FAVORITE_SUCCESS = 0x10; public static final int RESULT_CODE_FAVORITE_UNDO_SUCCESS = 0x11; public static final int QA = 0x1001; public static final int FAVORITE = 0x1002; public static final int FAVORITE_UNDO = 0x1003; public QuestionDetailsIntentService() { this(TAG); } public QuestionDetailsIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { final ResultReceiver receiver = intent.getParcelableExtra(StringConstants.RESULT_RECEIVER); final int action = intent.getIntExtra(StringConstants.ACTION, -1); final long questionId = intent.getLongExtra(StringConstants.ID, 0); final String site = intent.getStringExtra(StringConstants.SITE); try { switch (action) { case QA: getQuestion(intent, receiver); break; case VotingActions.UPVOTE: sendSerializable(receiver, VotingActions.RESULT_CODE_UPVOTE_SUCCESS, StringConstants.SCORE, questionService.upvote(PostType.QUESTION, site, questionId)); break; case VotingActions.UPVOTE_UNDO: sendSerializable(receiver, VotingActions.RESULT_CODE_UPVOTE_UNDO_SUCCESS, StringConstants.SCORE, questionService.undoUpvote(PostType.QUESTION, site, questionId)); break; case VotingActions.DOWNVOTE: sendSerializable(receiver, VotingActions.RESULT_CODE_DOWNVOTE_SUCCESS, StringConstants.SCORE, questionService.downvote(PostType.QUESTION, site, questionId)); break; case VotingActions.DOWNVOTE_UNDO: sendSerializable(receiver, VotingActions.RESULT_CODE_DOWNVOTE_UNDO_SUCCESS, StringConstants.SCORE, questionService.undoDownvote(PostType.QUESTION, site, questionId)); break; case VotingActions.UPVOTE_UNDO_DOWNVOTE: questionService.undoUpvote(PostType.QUESTION, site, questionId); sendSerializable(receiver, VotingActions.RESULT_CODE_UPVOTE_UNDO_DOWNVOTE_SUCCESS, StringConstants.SCORE, questionService.downvote(PostType.QUESTION, site, questionId)); break; case VotingActions.DOWNVOTE_UNDO_UPVOTE: questionService.undoDownvote(PostType.QUESTION, site, questionId); sendSerializable(receiver, VotingActions.RESULT_CODE_DOWNVOTE_UNDO_UPVOTE_SUCCESS, StringConstants.SCORE, questionService.upvote(PostType.QUESTION, site, questionId)); break; case FAVORITE: questionService.favorite(site, questionId); sendSerializable(receiver, RESULT_CODE_FAVORITE_SUCCESS, null, null); break; case FAVORITE_UNDO: questionService.undoFavorite(site, questionId); sendSerializable(receiver, RESULT_CODE_FAVORITE_UNDO_SUCCESS, null, null); break; default: sendSerializable(receiver, ERROR, "reason", "unrecognizable action"); break; } } catch (AbstractHttpException e) { Bundle bundle = new Bundle(); bundle.putSerializable(StringConstants.EXCEPTION, e); receiver.send(ERROR, bundle); } } private void getQuestion(Intent intent, ResultReceiver receiver) { final String action = intent.getAction(); if (action != null) { if (action.equals(StringConstants.ANSWERS)) { long questionId = intent.getLongExtra(StringConstants.QUESTION_ID, 0L); int page = intent.getIntExtra(StringConstants.PAGE, 0); final String site = intent.getStringExtra(StringConstants.SITE); if (questionId > 0 && page > 0) getAnswersForQuestion(receiver, site, questionId, page); } else { getQuestionDetail(receiver, intent); } } } private void getAnswersForQuestion(final ResultReceiver receiver, String site, long questionId, int page) { ArrayList<Answer> answers = getAnswersAndSend(receiver, site, questionId, page); QuestionsCache.getInstance().updateAnswersForQuestion(questionId, answers); } private void getQuestionDetail(ResultReceiver receiver, Intent intent) { long questionId = intent.getLongExtra(StringConstants.QUESTION_ID, 0); final String site = intent.getStringExtra(StringConstants.SITE); Question question = null; if (!intent.getBooleanExtra(StringConstants.REFRESH, false)) question = QuestionsCache.getInstance().get(questionId); if (question != null) { LogWrapper.d(TAG, "Question " + questionId + " recovered from cache."); sendSerializable(receiver, RESULT_CODE_Q_CACHED, StringConstants.QUESTION, question); } else { if (StringConstants.QUESTION.equals(intent.getAction())) { question = (Question) intent.getSerializableExtra(StringConstants.QUESTION); getQuestionAndAnswers(site, receiver, question); } else { LogWrapper.d(TAG, "Get question for " + questionId + " in " + site); question = getQuestionMetaAndBodyAndSend(site, receiver, questionId); } QuestionsCache.getInstance().add(question.id, question); } } private void getQuestionAndAnswers(String site, ResultReceiver receiver, Question question) { question.body = questionService.getQuestionBodyForId(question.id); sendSerializable(receiver, RESULT_CODE_Q_BODY, StringConstants.BODY, question.body); getCommentsAndSend(site, receiver, question); if (question.answerCount > 0) question.answers = getAnswersAndSend(receiver, site, question.id, 1); } private void getCommentsAndSend(String site, ResultReceiver receiver, Question question) { try { StackXPage<Comment> commentsPage = questionService.getComments(StringConstants.QUESTIONS, site, String.valueOf(question.id), 1); if (commentsPage != null) { question.comments = commentsPage.items; sendSerializable(receiver, RESULT_CODE_Q_COMMENTS, StringConstants.COMMENTS, question.comments); } } catch (AbstractHttpException e) { LogWrapper.e(TAG, e.getMessage()); } } private Question getQuestionMetaAndBodyAndSend(String site, ResultReceiver receiver, long questionId) { Question question = questionService.getQuestionFullDetails(questionId, site); sendSerializable(receiver, RESULT_CODE_Q, StringConstants.QUESTION, question); getCommentsAndSend(site, receiver, question); return question; } private ArrayList<Answer> getAnswersAndSend(final ResultReceiver receiver, String site, long questionId, int page) { ArrayList<Answer> answers = questionService.getAnswersForQuestion(questionId, site, page); sendSerializable(receiver, RESULT_CODE_ANSWERS, StringConstants.ANSWERS, answers); return answers; } private void sendSerializable(ResultReceiver receiver, int resultCode, String key, Serializable value) { Bundle bundle = new Bundle(); if (key != null && value != null) bundle.putSerializable(key, value); receiver.send(resultCode, bundle); } }