/**
* Copyright (C) 2013 - 2015 the enviroCar community
* <p>
* This file is part of the enviroCar app.
* <p>
* The enviroCar app 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.
* <p>
* The enviroCar app 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.
* <p>
* You should have received a copy of the GNU General Public License along
* with the enviroCar app. If not, see http://www.gnu.org/licenses/.
*/
package org.envirocar.app.handler;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import com.squareup.otto.Bus;
import org.envirocar.app.R;
import org.envirocar.app.exception.NotLoggedInException;
import org.envirocar.core.UserManager;
import org.envirocar.core.entity.User;
import org.envirocar.core.entity.UserImpl;
import org.envirocar.core.events.NewUserSettingsEvent;
import org.envirocar.core.exception.UnauthorizedException;
import org.envirocar.core.injection.InjectApplicationScope;
import org.envirocar.core.logging.Logger;
import org.envirocar.remote.DAOProvider;
import org.envirocar.remote.gravatar.GravatarUtils;
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import rx.Observable;
import rx.exceptions.OnErrorThrowable;
import rx.functions.Func1;
import static android.content.Context.MODE_PRIVATE;
/**
* TODO JavaDoc
*
* @author dewall
*/
@Singleton
public class UserHandler implements UserManager {
private static final Logger LOG = Logger.getLogger(UserHandler.class);
private static final String USERNAME = "username";
private static final String TOKEN = "token";
private static final String EMAIL = "email";
private static final String ACCEPTED_TERMS_OF_USE_VERSION = "acceptedTermsOfUseVersion";
private static final String USER_PREFERENCES = "userPrefs";
private final Context context;
private final Bus bus;
private final DAOProvider daoProvider;
private User mUser;
private Bitmap mGravatarBitmap;
/**
* Constructor.
*
* @param context the context of the current scope.
*/
@Inject
public UserHandler(@InjectApplicationScope Context context, Bus bus, DAOProvider daoProvider) {
this.context = context;
this.bus = bus;
this.daoProvider = daoProvider;
}
/**
* Get the user
*
* @return user
*/
@Override
public User getUser() {
if (mUser == null) {
SharedPreferences prefs = getUserPreferences();
String username = prefs.getString(USERNAME, null);
String token = prefs.getString(TOKEN, null);
String mail = prefs.getString(EMAIL, null);
mUser = new UserImpl(username, token, mail);
mUser.setTermsOfUseVersion(prefs.getString(ACCEPTED_TERMS_OF_USE_VERSION, null));
}
return mUser;
}
/**
* Set the user in the private user preferences
*
* @param user The user you want to set
*/
@Override
public void setUser(User user) {
// First set the user in the preferences
Editor e = getUserPreferences().edit();
e.putString(USERNAME, user.getUsername());
e.putString(TOKEN, user.getToken());
e.putString(EMAIL, user.getMail());
e.putString(ACCEPTED_TERMS_OF_USE_VERSION, user.getTermsOfUseVersion());
e.commit();
// Set the local user reference to the current user.
mUser = user;
bus.post(new NewUserSettingsEvent(user, true));
}
/**
* Determines whether the user is logged in. A user is logged in when
* the application has a user as a variable.
*
* @return
*/
@Override
public boolean isLoggedIn() {
SharedPreferences prefs = getUserPreferences();
if (prefs.contains(USERNAME) && prefs.contains(TOKEN)) {
return true;
} else {
return false;
}
}
public <T> Func1<T, T> getIsLoggedIn() {
return new Func1<T, T>() {
@Override
public T call(T t) {
if (isLoggedIn())
return t;
else
throw OnErrorThrowable.from(new NotLoggedInException(context.getString(R
.string.trackviews_not_logged_in)));
}
};
}
/**
* Logs out the user.
*/
@Override
public void logOut() {
logOut(false);
}
private void logOut(boolean withoutEvent) {
// Removes all the preferences from the editor.
SharedPreferences prefs = getUserPreferences();
Editor e = prefs.edit();
if (prefs.contains(USERNAME))
e.remove(USERNAME);
if (prefs.contains(TOKEN))
e.remove(TOKEN);
if (prefs.contains(EMAIL))
e.remove(EMAIL);
if (prefs.contains(ACCEPTED_TERMS_OF_USE_VERSION))
e.remove(ACCEPTED_TERMS_OF_USE_VERSION);
e.commit();
// Remove the user instance.
mUser = null;
mGravatarBitmap = null;
// Delete all local representations of tracks that are already uploaded.
// mTrackRecordingHandler.deleteAllRemoteTracksLocally();
// Fire a new event on the event bus holding indicating that no logged in user exist.
if (!withoutEvent) {
bus.post(new NewUserSettingsEvent(null, false));
}
}
/**
* Method used for authentication (e.g. at loginscreen to verify user
* credentials
*/
public void logIn(String user, String token, LoginCallback callback) {
User currentUser = getUser();
if (currentUser == null || currentUser.getToken() == null) {
User candidateUser = new UserImpl(user, token);
setUser(candidateUser);
}
try {
User result = daoProvider.getUserDAO().getUser(user);
result.setToken(token);
setUser(result);
// Successfully logged in. Inform the callback about this.
callback.onSuccess(result);
return;
} catch (UnauthorizedException e) {
LOG.warn(e.getMessage(), e);
logOut(true);
// Password is incorrect. Inform the callback about this.
callback.onPasswordIncorrect(token);
} catch (Exception e) {
LOG.warn(e.getMessage(), e);
logOut(true);
// Unable to communicate with the server. Inform the callback about this.
callback.onUnableToCommunicateServer();
}
}
public Observable<Bitmap> getGravatarBitmapObservable() {
return Observable.just(true)
.map(aBoolean -> {
if (isLoggedIn()) {
// If the gravatar bitmap already exist, then return it.
if (mGravatarBitmap != null)
return mGravatarBitmap;
// Else try to download the bitmap.
// But first check whether all required credentials are valid.
User user = getUser();
String mail = user.getMail();
if (mail == null || mail.equals("") || mail.isEmpty())
return null;
// Try to download the bitmap.
try {
mGravatarBitmap = GravatarUtils.downloadBitmap(user.getMail());
return mGravatarBitmap;
} catch (IOException e) {
LOG.warn("Error while downloading Gravatar bitmap.", e);
e.printStackTrace();
}
}
return null;
});
}
/**
* Get a user object from the shared preferences
*
* @return the user that is stored on the device
*/
private SharedPreferences getUserPreferences() {
SharedPreferences userPrefs = context.getSharedPreferences(USER_PREFERENCES, MODE_PRIVATE);
return userPrefs;
}
}