package com.aliao.android.hipster;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
/**
* The main activity used to connect to other Hipsters!
*/
public class ConnectActivity extends SherlockActivity implements View.OnClickListener {
// Keys to restore the activity instance state.
private static final String SAVED_INSTANCE_TARGET_HIPSTER_KEY = "target_hipster";
private static final String SAVED_INSTANCE_TARGET_PHOTO_KEY = "target_photo";
private static final String SAVED_INSTANCE_SCORE_KEY = "score";
// Current user score not fetched sentinel value.
private static final int NO_SCORE = -1;
// View references.
private TextView scoreLabel;
private ImageView hipsterImage;
private TextView hipsterName;
private EditText hipsterCodeInput;
private View connectButton;
private TextView skipButton;
private ProgressBar loadingSpinner;
// Current user score
private int score = NO_SCORE;
// Target references.
private HipsterUser targetHipster;
private Bitmap targetHipsterBitmap;
// Available server actions.
private HipsterActions actions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connect);
// Obtain UI references.
hipsterImage = (ImageView) findViewById(R.id.photo);
hipsterName = (TextView) findViewById(R.id.name);
hipsterCodeInput = (EditText) findViewById(R.id.code);
connectButton = findViewById(R.id.connect);
connectButton.setOnClickListener(this);
skipButton = (TextView) findViewById(R.id.skip);
skipButton.setOnClickListener(this);
loadingSpinner = (ProgressBar) findViewById(android.R.id.progress);
// Get server actions.
HipsterPartyApp application = (HipsterPartyApp) getApplication();
actions = application.getUserActions();
// Display the current user's verification code in the action bar.
HipsterUser currentUser = actions.getCurrentUser();
ActionBar actionBar = getSupportActionBar();
String codeTitle = String.format(getString(R.string.subtitle_code),
currentUser.getVerificationCode());
actionBar.setSubtitle(codeTitle);
// Get the saved state if available.
if (savedInstanceState != null) {
targetHipster = savedInstanceState.getParcelable(SAVED_INSTANCE_TARGET_HIPSTER_KEY);
targetHipsterBitmap = savedInstanceState.getParcelable(SAVED_INSTANCE_TARGET_PHOTO_KEY);
score = savedInstanceState.getInt(SAVED_INSTANCE_SCORE_KEY);
}
// Show the target hipster info.
if (targetHipster == null) {
fetchTargetHipster();
} else {
renderTargetHipster(targetHipster);
// Render the bitmap only when the target hipster is present.
if (targetHipsterBitmap == null) {
fetchHipsterPhoto(targetHipster);
} else {
renderHipsterPhoto(targetHipsterBitmap);
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(SAVED_INSTANCE_TARGET_HIPSTER_KEY, targetHipster);
outState.putParcelable(SAVED_INSTANCE_TARGET_PHOTO_KEY, targetHipsterBitmap);
outState.putInt(SAVED_INSTANCE_SCORE_KEY, score);
}
private void fetchCurrentUserScore() {
actions.getUserScoreAsync(actions.getCurrentUser(), new HipsterActions.OnScoreCallback() {
@Override
public void onSuccess(HipsterUser user, int score) {
ConnectActivity.this.score = score;
renderCurrentUserScore(score);
}
@Override
public void onError(Exception exception) {
Toast.makeText(ConnectActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void renderCurrentUserScore(int score) {
if (score == NO_SCORE) {
scoreLabel.setText("");
} else {
scoreLabel.setText(score + " " + getString(R.string.points_abbreviation));
}
}
private void fetchTargetHipster() {
renderLoadingState(true);
actions.getRandomHipsterAsync(new HipsterActions.OnNextUserFoundCallback() {
@Override
public void onSuccess(HipsterUser nextUser) {
renderLoadingState(false);
targetHipster = nextUser;
renderTargetHipster(nextUser);
fetchHipsterPhoto(nextUser);
}
@Override
public void onError(Exception exception) {
renderLoadingState(false);
Toast.makeText(ConnectActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void renderLoadingState(boolean isFetching) {
loadingSpinner.setVisibility(!isFetching ? View.GONE : View.VISIBLE);
connectButton.setEnabled(!isFetching);
skipButton.setEnabled(!isFetching);
}
private void renderTargetHipster(HipsterUser hipster) {
String userName = hipster.getUserName();
hipsterName.setText(userName);
String codeHint = getString(R.string.enter_code);
hipsterCodeInput.setText("");
hipsterCodeInput.setHint(String.format(codeHint, userName));
String skipText = getString(R.string.skip);
skipButton.setText(String.format(skipText, userName));
}
private void fetchHipsterPhoto(HipsterUser connectToUser) {
hipsterImage.setImageResource(R.drawable.hipster_user);
if (targetHipsterBitmap != null) {
targetHipsterBitmap.recycle();
targetHipsterBitmap = null;
}
actions.getUserPhotoAsync(connectToUser, new HipsterActions.OnPhotoCallback() {
@Override
public void onSuccess(HipsterUser user, Bitmap photo) {
targetHipsterBitmap = photo;
renderHipsterPhoto(photo);
}
@Override
public void onError(Exception exception) {
Toast.makeText(ConnectActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void renderHipsterPhoto(Bitmap bitmap) {
hipsterImage.setImageBitmap(bitmap);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.connect, menu);
// This custom menu item displays the user's score.
MenuItem scoreMenuItem = menu.findItem(R.id.menu_score);
scoreLabel = (TextView) scoreMenuItem.getActionView();
// Show the current user score.
if (score == NO_SCORE) {
fetchCurrentUserScore();
} else {
renderCurrentUserScore(score);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_refresh) {
fetchCurrentUserScore();
return true;
}
if (itemId == R.id.menu_leaderboard) {
startActivity(new Intent(this, LeaderBoardActivity.class));
return true;
}
return super.onMenuItemSelected(featureId, item);
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.skip) {
fetchTargetHipster();
return;
}
if (id == R.id.connect) {
// Can't connect if there is no target hipster.
if (targetHipster == null) {
return;
}
// Client-side check for the hipster code. A more secure implementation might check on the
// server, but this isn't critical.
if (verifyCode(targetHipster, hipsterCodeInput.getText().toString())) {
connect(actions.getCurrentUser(), targetHipster);
}
}
}
private boolean verifyCode(HipsterUser hipsterUser, String typedCode) {
if (!hipsterUser.getVerificationCode().equals(typedCode)) {
Toast.makeText(ConnectActivity.this, getString(R.string.error_connect_code) +
hipsterUser.getUserName(), Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
private void connect(HipsterUser currentUser, HipsterUser targetHipster) {
renderLoadingState(true);
connectButton.setEnabled(false);
loadingSpinner.setVisibility(View.VISIBLE);
HipsterPartyApp application = (HipsterPartyApp) getApplication();
application.getUserActions().connectUserAsync(currentUser, targetHipster,
new HipsterActions.OnConnectUserCallback() {
@Override
public void onSuccess(HipsterUser userFrom, HipsterUser userTo) {
renderLoadingState(false);
fetchCurrentUserScore();
fetchTargetHipster();
}
@Override
public void onError(Exception exception) {
renderLoadingState(false);
Toast.makeText(ConnectActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}