package com.kenny.openimgur.activities;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.CookieManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.kenny.openimgur.R;
import com.kenny.openimgur.api.ApiClient;
import com.kenny.openimgur.api.OAuthInterceptor;
import com.kenny.openimgur.api.responses.UserResponse;
import com.kenny.openimgur.classes.ImgurUser;
import com.kenny.openimgur.fragments.ProfileAlbumsFragment;
import com.kenny.openimgur.fragments.ProfileCommentsFragment;
import com.kenny.openimgur.fragments.ProfileFavoritesFragment;
import com.kenny.openimgur.fragments.ProfileInfoFragment;
import com.kenny.openimgur.fragments.ProfileMessagesFragment;
import com.kenny.openimgur.fragments.ProfileSubmissionsFragment;
import com.kenny.openimgur.fragments.ProfileUploadsFragment;
import com.kenny.openimgur.services.AlarmReceiver;
import com.kenny.openimgur.ui.ViewPager;
import com.kenny.openimgur.util.LogUtil;
import com.kenny.openimgur.util.SqlHelper;
import com.kenny.openimgur.util.ViewUtils;
import com.kennyc.view.MultiStateView;
import butterknife.BindView;
import butterknife.OnClick;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Created by kcampagna on 12/14/14.
*/
public class ProfileActivity extends BaseActivity {
private static final String LOGIN_URL = "https://api.imgur.com/oauth2/authorize?client_id=" + ApiClient.CLIENT_ID + "&response_type=token";
private static final String REDIRECT_URL = "https://com.kenny.openimgur";
public static final String KEY_LOGGED_IN = "logged_in";
public static final String KEY_LOGGED_OUT = "logged_out";
private static final String KEY_USERNAME = "username";
private static final String KEY_USER = "user";
private static final String KEY_IS_LOGGING_IN = "is_logging_in";
@BindView(R.id.slidingTabs)
TabLayout mSlidingTabs;
@BindView(R.id.pager)
ViewPager mPager;
@BindView(R.id.multiView)
MultiStateView mMultiView;
@BindView(R.id.toolBar)
Toolbar mToolBar;
ImgurUser mSelectedUser;
ProfilePager mAdapter;
public static Intent createIntent(Context context, @Nullable String userName) {
return createIntent(context, userName, false);
}
public static Intent createIntent(@NonNull Context context, @Nullable String userName, boolean isLoggingIn) {
Intent intent = new Intent(context, ProfileActivity.class);
if (!TextUtils.isEmpty(userName)) intent.putExtra(KEY_USERNAME, userName);
return intent.putExtra(KEY_IS_LOGGING_IN, isLoggingIn);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
setStatusBarColorResource(theme.darkColor);
setupToolBar();
handleData(savedInstanceState, getIntent());
}
/**
* Sets up the tool bar to take the place of the action bar
*/
private void setupToolBar() {
setSupportActionBar(mToolBar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
private void handleData(Bundle savedInstanceState, Intent args) {
if (savedInstanceState == null) {
if (args.hasExtra(KEY_USERNAME)) {
LogUtil.v(TAG, "User present in Bundle extras");
String username = args.getStringExtra(KEY_USERNAME);
mSelectedUser = SqlHelper.getInstance(getApplicationContext()).getUser(username);
configUser(username);
} else if (user != null) {
LogUtil.v(TAG, "User already logged in");
mSelectedUser = user;
configUser(null);
} else {
LogUtil.v(TAG, "No user present. Showing Login screen");
configWebView();
}
} else if (savedInstanceState.containsKey(KEY_USER)) {
mSelectedUser = savedInstanceState.getParcelable(KEY_USER);
configUser(null);
}
}
private void configUser(String username) {
mMultiView.setViewState(MultiStateView.VIEW_STATE_LOADING);
// Load the new user data if we haven't viewed the user within 24 hours
if (mSelectedUser == null || System.currentTimeMillis() - mSelectedUser.getLastSeen() >= DateUtils.DAY_IN_MILLIS) {
LogUtil.v(TAG, "Selected user is null or data is too old, fetching new data");
String userName = mSelectedUser == null ? username : mSelectedUser.getUsername();
getSupportActionBar().setTitle(userName);
fetchProfile(userName);
} else {
LogUtil.v(TAG, "Selected user present in database and has valid data");
mAdapter = new ProfilePager(getApplicationContext(), getFragmentManager(), mSelectedUser);
mPager.setAdapter(mAdapter);
mSlidingTabs.setupWithViewPager(mPager);
mMultiView.setViewState(MultiStateView.VIEW_STATE_CONTENT);
getSupportActionBar().setTitle(mSelectedUser.getUsername());
supportInvalidateOptionsMenu();
}
}
public void onUserLogout() {
mSelectedUser = null;
app.onLogout();
configWebView();
setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_LOGGED_OUT, true));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.profile, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.logout).setVisible(mSelectedUser != null && mSelectedUser.isSelf(app));
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.logout:
new AlertDialog.Builder(ProfileActivity.this, theme.getAlertDialogTheme())
.setTitle(R.string.logout)
.setMessage(R.string.logout_confirm)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onUserLogout();
}
}).show();
break;
}
return super.onOptionsItemSelected(item);
}
/**
* Configures the webview to handle a user logging in
*/
private void configWebView() {
getSupportActionBar().hide();
mMultiView.setViewState(MultiStateView.VIEW_STATE_EMPTY);
WebView webView = (WebView) mMultiView.getView(MultiStateView.VIEW_STATE_EMPTY).findViewById(R.id.loginWebView);
webView.loadUrl(LOGIN_URL);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(REDIRECT_URL)) {
if (url.contains("/?error=")) {
LogUtil.v(TAG, "Error received from URL " + url);
view.loadUrl(LOGIN_URL);
return true;
}
// We will extract the info from the callback url
mMultiView.setViewState(MultiStateView.VIEW_STATE_LOADING);
String[] outerSplit = url.split("\\#")[1].split("\\&");
String username = null;
String accessToken = null;
String refreshToken = null;
long accessTokenExpiration = 0;
int index = 0;
for (String s : outerSplit) {
String[] innerSplit = s.split("\\=");
switch (index) {
// Access Token
case 0:
accessToken = innerSplit[1];
break;
// Access Token Expiration
case 1:
long expiresIn = Long.parseLong(innerSplit[1]);
accessTokenExpiration = System.currentTimeMillis() + (expiresIn * DateUtils.SECOND_IN_MILLIS);
break;
// Token Type, not using
case 2:
//NO OP
break;
// Refresh Token
case 3:
refreshToken = innerSplit[1];
break;
// Username
case 4:
username = innerSplit[1];
break;
}
index++;
}
// Make sure that everything was set
if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(accessToken) &&
!TextUtils.isEmpty(refreshToken) && accessTokenExpiration > 0) {
ImgurUser newUser = new ImgurUser(username, accessToken, refreshToken, accessTokenExpiration);
app.setUser(newUser);
user = newUser;
mSelectedUser = newUser;
OAuthInterceptor.setAccessToken(accessToken);
LogUtil.v(TAG, "User " + newUser.getUsername() + " logged in");
fetchProfile(mSelectedUser.getUsername());
CookieManager.getInstance().removeAllCookie();
view.clearHistory();
view.clearCache(true);
view.clearFormData();
getSupportActionBar().show();
getSupportActionBar().setTitle(user.getUsername());
setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_LOGGED_IN, true));
AlarmReceiver.createNotificationAlarm(getApplicationContext());
} else {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.error_generic);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
} else {
view.loadUrl(url);
}
return true;
}
});
}
@OnClick(R.id.errorButton)
public void retryClick() {
if (mSelectedUser != null) fetchProfile(mSelectedUser.getUsername());
}
void fetchProfile(final String username) {
ApiClient.getService().getProfile(username).enqueue(new Callback<UserResponse>() {
@Override
public void onResponse(Call<UserResponse> call, Response<UserResponse> response) {
if (isDestroyed() || isFinishing()) return;
if (response != null && response.body() != null) {
UserResponse userResponse = response.body();
if (mSelectedUser != null) {
mSelectedUser.copy(userResponse.data);
} else {
mSelectedUser = userResponse.data;
}
mSelectedUser.setLastSeen(System.currentTimeMillis());
if (mSelectedUser.isSelf(app) && !TextUtils.isEmpty(mSelectedUser.getAccessToken())) {
SqlHelper.getInstance(getApplicationContext()).updateUserInfo(mSelectedUser);
Intent intent = getIntent();
// If we are logging in for an upload, return
if (intent != null && intent.getBooleanExtra(KEY_IS_LOGGING_IN, false)) {
finish();
return;
}
} else {
SqlHelper.getInstance(getApplicationContext()).insertProfile(mSelectedUser);
}
mAdapter = new ProfilePager(getApplicationContext(), getFragmentManager(), mSelectedUser);
mPager.setAdapter(mAdapter);
mSlidingTabs.setupWithViewPager(mPager);
mMultiView.setViewState(MultiStateView.VIEW_STATE_CONTENT);
supportInvalidateOptionsMenu();
} else {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, getString(R.string.profile_not_found, username));
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
}
@Override
public void onFailure(Call<UserResponse> call, Throwable t) {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, ApiClient.getErrorCode(t));
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mSelectedUser != null) {
outState.putParcelable(KEY_USER, mSelectedUser);
}
}
@Override
protected int getStyleRes() {
return theme.isDarkTheme ? R.style.Theme_Opengur_Dark_Main_Dark : R.style.Theme_Opengur_Light_Main_Light;
}
private static class ProfilePager extends FragmentStatePagerAdapter {
private static final int NUM_PAGES_SELF = 7;
private static final int NUM_PAGES_FAR = 5;
private String[] mTitles;
private ImgurUser mUser;
private int mNumPages;
public ProfilePager(Context context, FragmentManager fm, ImgurUser user) {
super(fm);
mTitles = context.getResources().getStringArray(R.array.profile_tabs);
mUser = user;
mNumPages = mUser.isSelf() ? NUM_PAGES_SELF : NUM_PAGES_FAR;
}
@Override
public Fragment getItem(int position) {
switch (position) {
// Info
case 0:
return ProfileInfoFragment.createInstance(mUser);
// Submissions
case 1:
return ProfileSubmissionsFragment.newInstance(mUser);
// Favorites
case 2:
return ProfileFavoritesFragment.newInstance(mUser);
// Albums
case 3:
return ProfileAlbumsFragment.createInstance(mUser);
// Comments
case 4:
return ProfileCommentsFragment.createInstance(mUser);
// Uploads
case 5:
return new ProfileUploadsFragment();
// Messages
case 6:
return new ProfileMessagesFragment();
default:
throw new IndexOutOfBoundsException("How did this happen?");
}
}
@Override
public int getCount() {
return mNumPages;
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
}
}