package com.boardgamegeek.ui;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.boardgamegeek.R;
import com.boardgamegeek.events.UpdateCompleteEvent;
import com.boardgamegeek.events.UpdateEvent;
import com.boardgamegeek.provider.BggContract.Buddies;
import com.boardgamegeek.provider.BggContract.PlayPlayers;
import com.boardgamegeek.provider.BggContract.PlayerColors;
import com.boardgamegeek.provider.BggContract.Plays;
import com.boardgamegeek.service.UpdateService;
import com.boardgamegeek.tasks.BuddyNicknameUpdateTask;
import com.boardgamegeek.tasks.RenamePlayerTask;
import com.boardgamegeek.ui.dialog.EditTextDialogFragment;
import com.boardgamegeek.ui.dialog.EditTextDialogFragment.EditTextDialogListener;
import com.boardgamegeek.ui.dialog.UpdateBuddyNicknameDialogFragment;
import com.boardgamegeek.ui.dialog.UpdateBuddyNicknameDialogFragment.UpdateBuddyNicknameDialogListener;
import com.boardgamegeek.ui.model.Buddy;
import com.boardgamegeek.ui.model.Player;
import com.boardgamegeek.ui.model.PlayerColor;
import com.boardgamegeek.ui.widget.TimestampView;
import com.boardgamegeek.util.ActivityUtils;
import com.boardgamegeek.util.ColorUtils;
import com.boardgamegeek.util.DialogUtils;
import com.boardgamegeek.util.HttpUtils;
import com.boardgamegeek.util.PresentationUtils;
import com.boardgamegeek.util.TaskUtils;
import com.boardgamegeek.util.UIUtils;
import com.boardgamegeek.util.fabric.DataManipulationEvent;
import com.squareup.picasso.Picasso;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import hugo.weaving.DebugLog;
import icepick.Icepick;
import icepick.State;
import timber.log.Timber;
public class BuddyFragment extends Fragment implements LoaderCallbacks<Cursor>, OnRefreshListener {
private static final int PLAYS_TOKEN = 1;
private static final int COLORS_TOKEN = 2;
private static final int TOKEN = 0;
private String buddyName;
private String playerName;
private boolean isRefreshing;
@State boolean hasBeenRefreshed;
private Unbinder unbinder;
private SwipeRefreshLayout swipeRefreshLayout;
@BindView(R.id.buddy_info) View buddyInfoView;
@BindView(R.id.full_name) TextView fullNameView;
@BindView(R.id.username) TextView usernameView;
@BindView(R.id.avatar) ImageView avatarView;
@BindView(R.id.nickname) TextView nicknameView;
@BindView(R.id.collection_card) View collectionCard;
@BindView(R.id.plays_card) View playsCard;
@BindView(R.id.plays_label) TextView playsView;
@BindView(R.id.wins_label) TextView winsView;
@BindView(R.id.wins_percentage) TextView winPercentageView;
@BindView(R.id.color_container) LinearLayout colorContainer;
@BindView(R.id.updated) TimestampView updatedView;
private int defaultTextColor;
private int lightTextColor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
final Intent intent = UIUtils.fragmentArgumentsToIntent(getArguments());
buddyName = intent.getStringExtra(ActivityUtils.KEY_BUDDY_NAME);
playerName = intent.getStringExtra(ActivityUtils.KEY_PLAYER_NAME);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_buddy, container, false);
unbinder = ButterKnife.bind(this, rootView);
buddyInfoView.setVisibility(isUser() ? View.VISIBLE : View.GONE);
collectionCard.setVisibility(isUser() ? View.VISIBLE : View.GONE);
updatedView.setVisibility(isUser() ? View.VISIBLE : View.GONE);
swipeRefreshLayout = (SwipeRefreshLayout) rootView;
if (isUser()) {
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setColorSchemeResources(PresentationUtils.getColorSchemeResources());
swipeRefreshLayout.setEnabled(true);
} else {
swipeRefreshLayout.setEnabled(false);
}
defaultTextColor = nicknameView.getTextColors().getDefaultColor();
lightTextColor = ContextCompat.getColor(getContext(), R.color.secondary_text);
if (isUser()) {
getLoaderManager().restartLoader(TOKEN, null, this);
} else {
nicknameView.setTextColor(defaultTextColor);
nicknameView.setText(playerName);
}
getLoaderManager().restartLoader(PLAYS_TOKEN, null, this);
getLoaderManager().restartLoader(COLORS_TOKEN, null, this);
return rootView;
}
private boolean isUser() {
return !TextUtils.isEmpty(buddyName);
}
@DebugLog
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@DebugLog
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
@Override
public void onDestroyView() {
if (unbinder != null) unbinder.unbind();
super.onDestroyView();
}
@SuppressWarnings("unused")
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onEvent(UpdateEvent event) {
isRefreshing = event.getType() == UpdateService.SYNC_TYPE_BUDDY;
updateRefreshStatus();
}
@SuppressWarnings("unused")
@DebugLog
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onEvent(UpdateCompleteEvent event) {
isRefreshing = false;
updateRefreshStatus();
}
private void updateRefreshStatus() {
if (swipeRefreshLayout != null) {
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(isRefreshing);
}
});
}
}
@Override
@DebugLog
public Loader<Cursor> onCreateLoader(int id, Bundle data) {
CursorLoader loader = null;
switch (id) {
case TOKEN:
loader = new CursorLoader(getActivity(), Buddies.buildBuddyUri(buddyName), Buddy.PROJECTION, null, null, null);
break;
case PLAYS_TOKEN:
if (isUser()) {
loader = new CursorLoader(getActivity(),
Plays.buildPlayersByUniqueUserUri(),
Player.PROJECTION,
PlayPlayers.USER_NAME + "=?",
new String[] { buddyName },
null);
} else {
loader = new CursorLoader(getActivity(),
Plays.buildPlayersByUniquePlayerUri(),
Player.PROJECTION,
"(" + PlayPlayers.USER_NAME + "=? OR " + PlayPlayers.USER_NAME + " IS NULL) AND play_players." + PlayPlayers.NAME + "=?",
new String[] { "", playerName },
null);
}
break;
case COLORS_TOKEN:
loader = new CursorLoader(getActivity(),
isUser() ? PlayerColors.buildUserUri(buddyName) : PlayerColors.buildPlayerUri(playerName),
PlayerColor.PROJECTION,
null, null, null);
break;
}
return loader;
}
@Override
@DebugLog
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (getActivity() == null) {
return;
}
switch (loader.getId()) {
case TOKEN:
onBuddyQueryComplete(cursor);
break;
case PLAYS_TOKEN:
onPlaysQueryComplete(cursor);
break;
case COLORS_TOKEN:
onColorsQueryComplete(cursor);
break;
default:
cursor.close();
break;
}
}
@Override
@DebugLog
public void onLoaderReset(Loader<Cursor> loader) {
}
@DebugLog
@OnClick(R.id.nickname)
public void onEditNicknameClick() {
if (isUser()) {
showNicknameDialog(nicknameView.getText().toString(), buddyName);
} else {
showPlayerNameDialog(nicknameView.getText().toString());
}
}
@DebugLog
@OnClick(R.id.collection_root)
public void onCollectionClick() {
Intent intent = new Intent(getActivity(), BuddyCollectionActivity.class);
intent.putExtra(ActivityUtils.KEY_BUDDY_NAME, buddyName);
startActivity(intent);
}
@DebugLog
@OnClick(R.id.plays_root)
public void onPlaysClick() {
if (isUser()) {
Intent intent = new Intent(getActivity(), BuddyPlaysActivity.class);
intent.putExtra(ActivityUtils.KEY_BUDDY_NAME, buddyName);
startActivity(intent);
} else {
Intent intent = new Intent(getActivity(), PlayerPlaysActivity.class);
intent.putExtra(ActivityUtils.KEY_PLAYER_NAME, playerName);
startActivity(intent);
}
}
@DebugLog
@OnClick(R.id.colors_root)
public void onColorsClick() {
Intent intent = new Intent(getActivity(), PlayerColorsActivity.class);
intent.putExtra(ActivityUtils.KEY_BUDDY_NAME, buddyName);
intent.putExtra(ActivityUtils.KEY_PLAYER_NAME, playerName);
startActivity(intent);
}
private void onBuddyQueryComplete(Cursor cursor) {
if (cursor == null || !cursor.moveToFirst()) {
requestRefresh();
return;
}
Buddy buddy = Buddy.fromCursor(cursor);
Picasso.with(getActivity())
.load(HttpUtils.ensureScheme(buddy.getAvatarUrl()))
.placeholder(R.drawable.person_image_empty)
.error(R.drawable.person_image_empty)
.fit().into(avatarView);
fullNameView.setText(buddy.getFullName());
usernameView.setText(buddyName);
if (TextUtils.isEmpty(buddy.getNickName())) {
nicknameView.setTextColor(lightTextColor);
nicknameView.setText(buddy.getFirstName());
} else {
nicknameView.setTextColor(defaultTextColor);
nicknameView.setText(buddy.getNickName());
}
updatedView.setTimestamp(buddy.getUpdated());
}
@DebugLog
private void onPlaysQueryComplete(Cursor cursor) {
if (cursor == null || !cursor.moveToFirst()) {
return;
}
Player player = Player.fromCursor(cursor);
final int playCount = player.getPlayCount();
final int winCount = player.getWinCount();
if (playCount > 0 || winCount > 0) {
playsCard.setVisibility(View.VISIBLE);
playsView.setText(PresentationUtils.getQuantityText(getContext(), R.plurals.plays_suffix, playCount, playCount));
winsView.setText(PresentationUtils.getQuantityText(getContext(), R.plurals.wins_suffix, winCount, winCount));
winPercentageView.setText(getString(R.string.percentage, (int) ((double) winCount / playCount * 100)));
} else {
playsCard.setVisibility(View.GONE);
}
}
@DebugLog
private void onColorsQueryComplete(Cursor cursor) {
if (cursor == null) {
return;
}
colorContainer.removeAllViews();
for (int i = 0; i < 3; i++) {
if (cursor.moveToNext()) {
colorContainer.setVisibility(View.VISIBLE);
ImageView view = createViewToBeColored();
PlayerColor color = PlayerColor.fromCursor(cursor);
ColorUtils.setColorViewValue(view, ColorUtils.parseColor(color.getColor()));
colorContainer.addView(view);
} else {
colorContainer.setVisibility(View.GONE);
return;
}
}
}
@DebugLog
private ImageView createViewToBeColored() {
ImageView view = new ImageView(getActivity());
int size = getResources().getDimensionPixelSize(R.dimen.color_circle_diameter_small);
int margin = getResources().getDimensionPixelSize(R.dimen.color_circle_diameter_small_margin);
LayoutParams lp = new LayoutParams(size, size);
lp.setMargins(margin, margin, margin, margin);
view.setLayoutParams(lp);
return view;
}
@DebugLog
@Override
public void onRefresh() {
requestRefresh();
}
@DebugLog
private void requestRefresh() {
if (!hasBeenRefreshed) {
forceRefresh();
hasBeenRefreshed = true;
}
}
@DebugLog
public void forceRefresh() {
if (isUser()) {
UpdateService.start(getActivity(), UpdateService.SYNC_TYPE_BUDDY, buddyName);
} else {
Timber.w("Something tried to refresh a player that wasn't a user!");
}
}
@DebugLog
private void showNicknameDialog(final String nickname, final String username) {
UpdateBuddyNicknameDialogFragment dialogFragment = UpdateBuddyNicknameDialogFragment.newInstance(R.string.title_edit_nickname, null, new UpdateBuddyNicknameDialogListener() {
@Override
public void onFinishEditDialog(String newNickname, boolean updatePlays) {
if (!TextUtils.isEmpty(newNickname)) {
BuddyNicknameUpdateTask task = new BuddyNicknameUpdateTask(getActivity(), username, newNickname, updatePlays);
TaskUtils.executeAsyncTask(task);
DataManipulationEvent.log("BuddyNickname", "Edit");
}
}
});
dialogFragment.setNickname(nickname);
DialogUtils.showFragment(getActivity(), dialogFragment, "edit_nickname");
}
@DebugLog
private void showPlayerNameDialog(final String oldName) {
EditTextDialogFragment editTextDialogFragment = EditTextDialogFragment.newInstance(R.string.title_edit_player, null, new EditTextDialogListener() {
@Override
public void onFinishEditDialog(String inputText) {
if (!TextUtils.isEmpty(inputText)) {
RenamePlayerTask task = new RenamePlayerTask(getContext(), oldName, inputText);
TaskUtils.executeAsyncTask(task);
}
}
});
editTextDialogFragment.setText(oldName);
DialogUtils.showFragment(getActivity(), editTextDialogFragment, "edit_player");
}
}