/*
Copyright (C) 2014 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.fragment;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.database.SQLException;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.prasanna.android.http.HttpException;
import com.prasanna.android.stacknetwork.R;
import com.prasanna.android.stacknetwork.adapter.ItemListAdapter;
import com.prasanna.android.stacknetwork.adapter.ItemListAdapter.ListItemView;
import com.prasanna.android.stacknetwork.model.Reputation;
import com.prasanna.android.stacknetwork.model.Site;
import com.prasanna.android.stacknetwork.model.StackXPage;
import com.prasanna.android.stacknetwork.model.User;
import com.prasanna.android.stacknetwork.receiver.RestQueryResultReceiver;
import com.prasanna.android.stacknetwork.receiver.RestQueryResultReceiver.StackXRestQueryResultReceiver;
import com.prasanna.android.stacknetwork.service.UserIntentService;
import com.prasanna.android.stacknetwork.sqlite.ProfileDAO;
import com.prasanna.android.stacknetwork.utils.AppUtils;
import com.prasanna.android.stacknetwork.utils.DateTimeUtils;
import com.prasanna.android.stacknetwork.utils.OperatingSite;
import com.prasanna.android.stacknetwork.utils.StringConstants;
import com.prasanna.android.task.AsyncTaskCompletionNotifier;
import com.prasanna.android.task.AsyncTaskExecutor;
import com.prasanna.android.task.GetImageAsyncTask;
import com.prasanna.android.utils.LogWrapper;
public class UserProfileFragment extends Fragment implements StackXRestQueryResultReceiver, ListItemView<Reputation> {
private static final String TAG = UserProfileFragment.class.getSimpleName();
private ViewGroup profileHomeLayout;
private Intent userProfileIntent;
private User user;
private boolean me = false;
private RestQueryResultReceiver resultReceiver;
private ArrayList<Reputation> repHistory = new ArrayList<Reputation>();
private ItemListAdapter<Reputation> itemListAdapter;
private long userId;
private boolean forceRefresh;
private Site site;
private Context appContext;
private ListView repHistoryView;
private int repHistoryPage = 1;
private ProgressBar progressBar;
private StackXPage<Reputation> repHistPage;
private AtomicBoolean repHistoryServiceRunning = new AtomicBoolean(false);
static class ReputationViewHolder {
TextView repChangeTv;
TextView repChangeTypeTv;
TextView postTitleTv;
}
static class PersistMyAvatarAsyncTask extends AsyncTask<Bitmap, Void, Void> {
private Context context;
public PersistMyAvatarAsyncTask(Context context) {
this.context = context;
}
@Override
protected Void doInBackground(Bitmap... params) {
ProfileDAO profileDAO = new ProfileDAO(context);
try {
profileDAO.open();
profileDAO.updateMyAvatar(OperatingSite.getSite().apiSiteParameter, params[0]);
} catch (SQLException e) {
LogWrapper.e(TAG, e.getMessage());
} finally {
profileDAO.close();
}
return null;
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
appContext = activity.getApplicationContext();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
resultReceiver = new RestQueryResultReceiver(new Handler());
resultReceiver.setReceiver(this);
if (savedInstanceState != null) {
me = savedInstanceState.getBoolean(StringConstants.ME);
userId = savedInstanceState.getLong(StringConstants.USER_ID);
site = (Site) savedInstanceState.getSerializable(StringConstants.SITE);
forceRefresh = false;
} else {
me = getActivity().getIntent().getBooleanExtra(StringConstants.ME, false);
userId = getActivity().getIntent().getLongExtra(StringConstants.USER_ID, 0L);
site = (Site) getActivity().getIntent().getSerializableExtra(StringConstants.SITE);
forceRefresh = getActivity().getIntent().getBooleanExtra(StringConstants.REFRESH, false);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (profileHomeLayout == null) {
profileHomeLayout = (ViewGroup) inflater.inflate(R.layout.user_proile_layout, container, false);
repHistoryView = (ListView) profileHomeLayout.findViewById(android.R.id.list);
repHistoryView.addFooterView(getProgressBar());
repHistoryView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (!repHistoryServiceRunning.get() && (totalItemCount - visibleItemCount) <= (firstVisibleItem + 1)) {
if (repHistPage != null && repHistPage.hasMore) startRepHistoryService();
}
}
});
itemListAdapter = new ItemListAdapter<Reputation>(getActivity(), R.layout.reputation, repHistory, this);
repHistoryView.setAdapter(itemListAdapter);
}
return profileHomeLayout;
}
@Override
public void onResume() {
super.onResume();
if (user == null) {
startUserProfileService();
if (me) startRepHistoryService();
} else {
showUserDetail();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(StringConstants.ME, me);
outState.putSerializable(StringConstants.SITE, site);
outState.putLong(StringConstants.USER_ID, getActivity().getIntent().getLongExtra(StringConstants.USER_ID, 0L));
super.onSaveInstanceState(outState);
}
private void startUserProfileService() {
getActivity().setProgressBarIndeterminateVisibility(true);
userProfileIntent = new Intent(getActivity(), UserIntentService.class);
userProfileIntent.putExtra(StringConstants.ACTION, UserIntentService.GET_USER_PROFILE);
userProfileIntent.putExtra(StringConstants.ME, me);
userProfileIntent.putExtra(StringConstants.USER_ID, userId);
userProfileIntent.putExtra(StringConstants.REFRESH, forceRefresh);
userProfileIntent.putExtra(StringConstants.RESULT_RECEIVER, resultReceiver);
userProfileIntent.putExtra(StringConstants.SITE, site.apiSiteParameter);
getActivity().startService(userProfileIntent);
}
private void startRepHistoryService() {
Intent intent = new Intent(getActivity(), UserIntentService.class);
if (intent != null) {
intent.putExtra(StringConstants.ACTION, UserIntentService.GET_USER_REP_HISTORY_FULL);
intent.putExtra(StringConstants.ME, getActivity().getIntent().getBooleanExtra(StringConstants.ME, false));
intent.putExtra(StringConstants.USER_ID, getActivity().getIntent().getLongExtra(StringConstants.USER_ID, 0L));
intent.putExtra(StringConstants.PAGE, repHistoryPage++);
intent.putExtra(StringConstants.RESULT_RECEIVER, resultReceiver);
progressBar.setVisibility(View.VISIBLE);
repHistoryServiceRunning.getAndSet(true);
getActivity().startService(intent);
}
}
private void showUserDetail() {
if (user != null && profileHomeLayout != null) {
if (isAdded()) getActivity().getActionBar().setTitle(Html.fromHtml(user.getDisplayName()) + "'s profile");
profileHomeLayout.findViewById(R.id.userProfile).setVisibility(View.VISIBLE);
showProfileInfo();
showItemsCount();
getAndDisplayUserAvatar();
}
}
private void showProfileInfo() {
TextView textView = (TextView) profileHomeLayout.findViewById(R.id.profileDisplayName);
textView.setText(Html.fromHtml(user.getDisplayName()));
textView = (TextView) profileHomeLayout.findViewById(R.id.registerDate);
textView.setText(getString(R.string.registered) + " " + DateTimeUtils.getElapsedDurationSince(user.creationDate));
textView = (TextView) profileHomeLayout.findViewById(R.id.profileUserReputation);
textView.setText(AppUtils.formatReputation(user.reputation));
textView = (TextView) profileHomeLayout.findViewById(R.id.profileViews);
textView.setText(getString(R.string.views) + " " + user.profileViews);
textView = (TextView) profileHomeLayout.findViewById(R.id.profileAcceptRate);
if (user.acceptRate > -1) textView.setText(getString(R.string.acceptRate) + " " + user.acceptRate + "%");
else textView.setVisibility(View.GONE);
textView = (TextView) profileHomeLayout.findViewById(R.id.profileUserLastSeen);
textView.setText(getString(R.string.lastSeen) + " " + DateTimeUtils.getElapsedDurationSince(user.lastAccessTime));
showBadgesCount();
}
private void showBadgesCount() {
if (user.badgeCounts != null && user.badgeCounts.length == 3) {
TextView textView = (TextView) profileHomeLayout.findViewById(R.id.profileUserGoldNum);
textView.setText(String.valueOf(user.badgeCounts[0]));
textView = (TextView) profileHomeLayout.findViewById(R.id.profileUserSilverNum);
textView.setText(String.valueOf(user.badgeCounts[1]));
textView = (TextView) profileHomeLayout.findViewById(R.id.profileUserBronzeNum);
textView.setText(String.valueOf(user.badgeCounts[2]));
}
}
private void showItemsCount() {
TextView textView = (TextView) profileHomeLayout.findViewById(R.id.questionCount);
textView.setText(getString(R.string.questions) + " " + String.valueOf(user.questionCount));
textView = (TextView) profileHomeLayout.findViewById(R.id.answerCount);
textView.setText(getString(R.string.answers) + " " + String.valueOf(user.answerCount));
textView = (TextView) profileHomeLayout.findViewById(R.id.upvoteCount);
textView.setText(getString(R.string.upvotes) + " " + String.valueOf(user.upvoteCount));
textView = (TextView) profileHomeLayout.findViewById(R.id.downvoteCount);
textView.setText(getString(R.string.downvotes) + " " + String.valueOf(user.downvoteCount));
}
private void getAndDisplayUserAvatar() {
if (user.avatar == null) runAsyncTaskToGetAvatar();
else displayAvatar(user.avatar);
}
private void runAsyncTaskToGetAvatar() {
final ProgressBar avatarProgressBar = (ProgressBar) profileHomeLayout.findViewById(R.id.getAvatarProgressBar);
avatarProgressBar.setVisibility(View.VISIBLE);
AsyncTaskCompletionNotifier<Bitmap> imageFetchAsyncTaskCompleteNotiferImpl =
new AsyncTaskCompletionNotifier<Bitmap>() {
@Override
public void notifyOnCompletion(Bitmap result) {
displayAvatar(result);
avatarProgressBar.setVisibility(View.GONE);
if (me) new PersistMyAvatarAsyncTask(appContext).execute(result);
}
};
AsyncTaskExecutor.getInstance().executeInThreadPoolExecutor(
new GetImageAsyncTask(imageFetchAsyncTaskCompleteNotiferImpl), user.profileImageLink);
}
private void displayAvatar(Bitmap result) {
ImageView userProfileImage = (ImageView) profileHomeLayout.findViewById(R.id.profileUserImage);
userProfileImage.setVisibility(View.VISIBLE);
userProfileImage.setImageBitmap(result);
}
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
if (isAdded() && isVisible()) getActivity().setProgressBarIndeterminateVisibility(false);
switch (resultCode) {
case UserIntentService.GET_USER_PROFILE:
showUserProfile(resultData);
break;
case UserIntentService.GET_USER_REP_HISTORY_FULL:
showRepHistory(resultData);
break;
case UserIntentService.ERROR:
ViewGroup errorView =
AppUtils.getErrorView(getActivity(), (HttpException) resultData.getSerializable(StringConstants.EXCEPTION));
profileHomeLayout.removeAllViews();
profileHomeLayout.addView(errorView);
break;
}
}
@SuppressWarnings("unchecked")
private void showUserProfile(Bundle resultData) {
StackXPage<User> userPage = (StackXPage<User>) resultData.getSerializable(StringConstants.USER);
if (isVisible() && userPage != null && userPage.items != null && !userPage.items.isEmpty()) {
user = userPage.items.get(0);
showUserDetail();
}
}
@SuppressWarnings("unchecked")
private void showRepHistory(Bundle resultData) {
repHistoryServiceRunning.getAndSet(false);
progressBar.setVisibility(View.GONE);
repHistPage = (StackXPage<Reputation>) resultData.getSerializable(StringConstants.REP_HISTORY);
if (repHistPage != null) {
repHistory.addAll(repHistPage.items);
itemListAdapter.notifyDataSetChanged();
}
}
@Override
public View getView(Reputation item, int position, View convertView, ViewGroup parent) {
ReputationViewHolder holder;
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.reputation, null);
holder = new ReputationViewHolder();
holder.repChangeTv = (TextView) convertView.findViewById(R.id.repChange);
holder.repChangeTypeTv = (TextView) convertView.findViewById(R.id.repChangeType);
holder.postTitleTv = (TextView) convertView.findViewById(R.id.postTitle);
convertView.setTag(holder);
} else holder = (ReputationViewHolder) convertView.getTag();
holder.repChangeTypeTv.setText(item.reputationHistoryType.getDisplayText());
if (item.reputationChange > 0) {
holder.repChangeTv.setTextColor(getActivity().getResources().getColor(R.color.positiveRepChange));
holder.repChangeTv.setText("+" + item.reputationChange);
} else {
holder.repChangeTv.setTextColor(getActivity().getResources().getColor(R.color.negativeRepChange));
holder.repChangeTv.setText(String.valueOf(item.reputationChange));
}
if (item.postTitle != null) holder.postTitleTv.setText(Html.fromHtml(item.postTitle));
else holder.postTitleTv.setText("Unknown post");
return convertView;
}
private ProgressBar getProgressBar() {
if (progressBar == null)
progressBar =
(ProgressBar) LayoutInflater.from(getActivity().getApplicationContext()).inflate(R.layout.progress_bar, null);
return progressBar;
}
}