/*
* Created by Itzik Braun on 12/3/2015.
* Copyright (c) 2015 deluge. All rights reserved.
*
* Last Modification at: 3/12/15 4:27 PM
*/
package com.braunster.chatsdk.Utils.helper;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.ProgressBar;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.braunster.chatsdk.R;
import com.braunster.chatsdk.Utils.ImageUtils;
import com.braunster.chatsdk.Utils.volley.VolleyUtils;
import com.braunster.chatsdk.dao.BUser;
import com.braunster.chatsdk.network.BDefines;
import com.braunster.chatsdk.network.BFacebookManager;
import com.braunster.chatsdk.network.BNetworkManager;
import com.braunster.chatsdk.network.TwitterManager;
import com.braunster.chatsdk.object.BError;
import com.braunster.chatsdk.object.Cropper;
import com.braunster.chatsdk.object.SaveImageProgress;
import com.soundcloud.android.crop.Crop;
import org.apache.commons.lang3.StringUtils;
import org.jdeferred.DoneCallback;
import org.jdeferred.FailCallback;
import org.jdeferred.Promise;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import de.hdodenhof.circleimageview.CircleImageView;
import timber.log.Timber;
public class ChatSDKProfileHelper {
public static final int ERROR = 1991, NOT_HANDLED = 1992, HANDELD = 1993;
private static final String LAST_IMAGE_PATH = "last_image_path";
private static final String TAG = ChatSDKProfileHelper.class.getSimpleName();
private static final boolean DEBUG = true;
private Cropper crop;
private Fragment fragment = null;
/** If this was set this is the user that will be used instead of the current user.*/
private BUser profileUser;
public static final int PROFILE_PIC = 100;
public CircleImageView profileCircleImageView;
public ProgressBar progressBar;
private Activity activity;
private ChatSDKUiHelper uiHelper;
private View mainView;
public ChatSDKProfileHelper(Activity activity, ChatSDKUiHelper uiHelper, View mainView) {
this.activity = activity;
this.uiHelper = uiHelper;
this.mainView = mainView;
}
public ChatSDKProfileHelper(Activity activity, CircleImageView profileCircleImageView, ProgressBar progressBar, ChatSDKUiHelper uiHelper, View mainView) {
this.profileCircleImageView = profileCircleImageView;
this.progressBar = progressBar;
this.activity = activity;
this.uiHelper = uiHelper;
this.mainView = mainView;
}
private static String lastImageLoadedPath = "";
private boolean saveImageWhenLoaded = true;
/* UI */
public void loadProfilePic(){
loadProfilePic(getLoginType());
}
public void loadProfilePic(int loginType){
profileCircleImageView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
if (StringUtils.isNotEmpty(lastImageLoadedPath))
{
setProfilePicFromPath(lastImageLoadedPath);
return;
}
switch (loginType)
{
case BDefines.BAccountType.Facebook:
getProfileFromFacebook();
break;
case BDefines.BAccountType.Password:
case BDefines.BAccountType.Custom:
case BDefines.BAccountType.Register:
if (profileUser==null)
setProfilePicFromURL(BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().metaStringForKey(BDefines.Keys.BPictureURL), false);
else setProfilePicFromURL(profileUser.metaStringForKey(BDefines.Keys.BPictureURL), false);
break;
case BDefines.BAccountType.Anonymous:
setInitialsProfilePic(BDefines.InitialsForAnonymous, true);
case BDefines.BAccountType.Twitter:
getProfileFromTwitter();
break;
}
}
private class PostProfilePic implements Runnable{
private Bitmap bitmap;
private PostProfilePic(Bitmap bitmap){
this.bitmap = bitmap;
}
@Override
public void run() {
int size = mainView.findViewById(R.id.frame_profile_image_container).getMeasuredHeight();
profileCircleImageView.setImageBitmap(scaleImage(bitmap, size));
progressBar.setVisibility(View.GONE);
profileCircleImageView.setVisibility(View.VISIBLE);
}
}
private PostProfilePic postProfilePic;
public void setProfilePic(final Bitmap bitmap){
// load image into imageview
final int size = mainView.findViewById(R.id.frame_profile_image_container).getMeasuredHeight();
if (loadFromUrl != null)
loadFromUrl.setKilled(true);
if (postProfilePic != null)
profileCircleImageView.removeCallbacks(postProfilePic);
// If the size of the container is 0 we will wait for the view to do onLayout and only then measure it.
if (size == 0)
{
postProfilePic = new PostProfilePic(bitmap);
profileCircleImageView.post(postProfilePic);
} else
{
profileCircleImageView.setImageBitmap(scaleImage(bitmap, size));
progressBar.setVisibility(View.GONE);
profileCircleImageView.setVisibility(View.VISIBLE);
}
}
public class LoadFromUrl implements ImageLoader.ImageListener{
private boolean killed = false;
private boolean saveAfterLoad = false;
public LoadFromUrl(){
}
public LoadFromUrl(boolean saveAfterLoad){
this.saveAfterLoad = saveAfterLoad;
}
public void setKilled(boolean killed) {
this.killed = killed;
}
@Override
public void onResponse(final ImageLoader.ImageContainer response, boolean isImmediate) {
if (killed)
return;
if (response.getBitmap() != null) {
setProfilePic(response.getBitmap());
if (saveAfterLoad)
createTempFileAndSave(response.getBitmap());
}
}
@Override
public void onErrorResponse(VolleyError error) {
if (DEBUG) Timber.e("Image Load Error: %s", error.getMessage());
setInitialsProfilePic(false);
}
};
private LoadFromUrl loadFromUrl;
public void setProfilePicFromURL(String url, boolean saveAfterLoad){
if (DEBUG) Timber.v("setProfilePicFromURL, Url: %s", url);
// Set default.
if (StringUtils.isEmpty(url))
{
// Loading the user image from robohash.
String name = profileUser == null ? BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().getMetaName() : profileUser.getMetaName();
url = BDefines.getDefaultImageUrl("http://robohash.org/" + name,
BDefines.ImageProperties.INITIALS_IMAGE_SIZE,
BDefines.ImageProperties.INITIALS_IMAGE_SIZE);
saveAfterLoad = true;
}
if (loadFromUrl != null)
loadFromUrl.setKilled(true);
loadFromUrl = new LoadFromUrl(saveAfterLoad);
VolleyUtils.getImageLoader().get(url, loadFromUrl);
}
/** Only for current user.*/
public Promise<String[], BError, SaveImageProgress> saveProfilePicToServer(String path, boolean setAsPic) {
// Loading the bitmap
if (setAsPic)
{
setProfilePicFromPath(path);
}
return saveProfilePicToServer(path);
}
/** Only for current user.*/
public void setProfilePicFromPath(String path){
Bitmap b = ImageUtils.loadBitmapFromFile(path);
if (b == null)
{
b = ImageUtils.loadBitmapFromFile(activity.getCacheDir().getPath() + path);
if (b == null)
{
uiHelper.showAlertToast(R.string.unable_to_save_file);
if (DEBUG) Timber.e("Cant save image to backendless file path is invalid: " + activity.getCacheDir().getPath() + path);
return;
}
}
setProfilePic(b);
}
/** Only for current user.*/
public Promise<String[], BError, SaveImageProgress> saveProfilePicToServer(String path){
Bitmap image = ImageUtils.getCompressed(path);
Bitmap thumbnail = ImageUtils.getCompressed(path,
BDefines.ImageProperties.MAX_IMAGE_THUMBNAIL_SIZE,
BDefines.ImageProperties.MAX_IMAGE_THUMBNAIL_SIZE);
return BNetworkManager.sharedManager().getNetworkAdapter().uploadImage(
image, thumbnail)
.done(new DoneCallback<String[]>() {
@Override
public void onDone(String[] data) {
// Saving the image to backendless.
final BUser currentUser = BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel();
currentUser.setMetaPictureUrl(data[0]);
currentUser.setMetaPictureThumbnail(data[1]);
BNetworkManager.sharedManager().getNetworkAdapter().pushUser();
}
})
.fail(new FailCallback<BError>() {
@Override
public void onFail(BError error) {
if (DEBUG)
Timber.e("Backendless Exception while saving profile pic, message: %s", error.message);
}
});
}
public void getProfileFromFacebook(){
// Use facebook profile picture only if has no other picture saved.
String imageUrl;
if (profileUser==null)
imageUrl = BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().getMetaPictureUrl();
else imageUrl = profileUser.getMetaPictureUrl();
if (StringUtils.isNotEmpty(imageUrl))
setProfilePicFromURL(imageUrl, false);
else
{
// Load the profile picture from facebook.
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
HttpURLConnection client = null;
try {
String facebookId;
String authId;
if (profileUser==null)
{
authId = BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().getEntityID();
}
else {
authId = profileUser.getEntityID().replace(BDefines.ProviderString.Facebook + ":", "");
if (StringUtils.isEmpty(authId)) {
authId = profileUser.getEntityID();
}
}
facebookId = authId.replace(BDefines.ProviderString.Facebook + ":", "");
if (DEBUG) Timber.d("Facebook Id: %s", facebookId);
String facebookImageUrl = BFacebookManager.getPicUrl(facebookId);
HttpURLConnection con = (HttpURLConnection) (new URL(facebookImageUrl).openConnection());
con.setInstanceFollowRedirects(false);
con.connect();
int responseCode = con.getResponseCode();
System.out.println(responseCode);
String location = con.getHeaderField("Location");
System.out.println(location);
return location;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
setProfilePicFromURL(s, true);
}
}.execute();
}
}
public void getProfileFromTwitter(){
// Use facebook profile picture only if has no other picture saved.
String savedUrl;
if (profileUser==null)
savedUrl = BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().getMetaPictureUrl();
else savedUrl = profileUser.getMetaPictureUrl();
if (StringUtils.isNotEmpty(savedUrl))
setProfilePicFromURL(savedUrl, false);
else {
String imageUrl = TwitterManager.profileImageUrl;
if (DEBUG) Timber.d("Twitter profile pic url: %s", TwitterManager.profileImageUrl);
if (StringUtils.isNotEmpty(imageUrl))
{
// The default image suppied by twitter is 48px on 48px image so we want a bigget one.
imageUrl = imageUrl.replace("_normal", "");
setProfilePicFromURL(imageUrl, true);
}
else
{
if (DEBUG) Timber.d("cant get twitter profile picture.");
setInitialsProfilePic(false);
}
}
}
public void setInitialsProfilePic(boolean save){
String initials = "";
String name;
if (profileUser==null)
name = BNetworkManager.sharedManager().getNetworkAdapter().currentUserModel().getMetaName();
else{
// We dont save initials image for other users.
save = false;
name = profileUser.getMetaName();
}
if (StringUtils.isEmpty(name))
initials = BDefines.InitialsForAnonymous;
else
{
String[] splited = name.split("\\s+");
if (splited.length == 1)
initials = String.valueOf(name.toUpperCase().charAt(0));
else if (splited.length >= 2)
initials = String.valueOf(splited[0].toUpperCase().charAt(0)) + String.valueOf(splited[1].toUpperCase().charAt(0));
else initials = BDefines.InitialsForAnonymous;
}
setInitialsProfilePic(initials, save);
}
public void setInitialsProfilePic(final String initials, boolean save) {
Bitmap bitmap = ImageUtils.getInitialsBitmap(Color.GRAY, Color.BLACK, initials);
setProfilePic(bitmap);
if (save)
createTempFileAndSave(bitmap);
}
public boolean createTempFileAndSave(Bitmap bitmap){
// Saving the image to tmp file.
try {
File tmp = File.createTempFile("Pic", ".jpg", activity.getCacheDir());
ImageUtils.saveBitmapToFile(tmp, bitmap);
saveProfilePicToServer(tmp.getPath(), false);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public Bitmap scaleImage(Bitmap bitmap, int boundBoxInDp){
if (boundBoxInDp == 0)
return null;
// Get current dimensions
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// Determine how much to scale: the dimension requiring less scaling is
// closer to the its side. This way the image always stays inside your
// bounding box AND either x/y axis touches it.
float xScale = ((float) boundBoxInDp) / width;
float yScale = ((float) boundBoxInDp) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap and convert it to a format understood by the ImageView
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
return bitmap;
}
public int handleResult(int requestCode, int resultCode, Intent data){
if (data == null)
{
return NOT_HANDLED;
}
if (requestCode == PROFILE_PIC)
{
if (resultCode == Activity.RESULT_OK)
{
Uri uri = data.getData();
Uri outputUri = Uri.fromFile(new File(this.activity.getCacheDir(), "cropped.jpg"));
crop = new Cropper(uri);
Intent cropIntent = crop.getIntent(this.activity, outputUri);
int request =Crop.REQUEST_CROP + PROFILE_PIC;
if (fragment==null)
activity.startActivityForResult(cropIntent, request);
else activity.startActivityFromFragment(fragment, cropIntent, request);
return HANDELD;
}
}
else if (requestCode == Crop.REQUEST_CROP + PROFILE_PIC) {
if (resultCode == Crop.RESULT_ERROR)
{
return ERROR;
}
try
{
File image;
Uri uri = Crop.getOutput(data);
if (DEBUG) Timber.d("Fetch image URI: %s", uri.toString());
image = new File(this.activity.getCacheDir(), "cropped.jpg");
lastImageLoadedPath = image.getPath();
if (saveImageWhenLoaded)
{
saveProfilePicToServer(lastImageLoadedPath, true)
.done(new DoneCallback<String[]>() {
@Override
public void onDone(String[] strings) {
// Resetting the selected path when done saving the image
lastImageLoadedPath = "";
}
});
}
else
setProfilePicFromPath(lastImageLoadedPath);
return HANDELD;
}
catch (NullPointerException e){
if (DEBUG) Timber.e("Null pointer when getting file.");
uiHelper.showAlertToast(R.string.unable_to_fetch_image);
return ERROR;
}
}
return NOT_HANDLED;
}
public void initViews(){
if (mainView!=null)
{
profileCircleImageView = (CircleImageView) mainView.findViewById(R.id.chat_sdk_circle_ing_profile_pic);
progressBar = (ProgressBar) mainView.findViewById(R.id.chat_sdk_progressbar);
}
}
public static View.OnClickListener getProfilePicClickListener(final Activity activity){
return ChatSDKIntentClickListener.getPickImageClickListener(activity, PROFILE_PIC);
}
public static View.OnClickListener getProfilePicClickListener(final Activity activity, final Fragment fragment){
return ChatSDKIntentClickListener.getPickImageClickListener(activity, fragment, PROFILE_PIC);
}
public static View.OnClickListener getPickImageClickListener(final FragmentActivity activity,final Fragment fragment, final int requestCode){
return ChatSDKIntentClickListener.getPickImageClickListener(activity, fragment, requestCode);
}
public static View.OnClickListener getPickImageClickListener(final FragmentActivity activity,final DialogFragment fragment, final int requestCode){
return ChatSDKIntentClickListener.getPickImageClickListener(activity, fragment, requestCode);
}
public Integer getLoginType(){
return (Integer) BNetworkManager.sharedManager().getNetworkAdapter().getLoginInfo().get(BDefines.Prefs.AccountTypeKey);
}
/** If set the helper will use this fragment when calling startActivityForResult*/
public void setFragment(Fragment fragment) {
this.fragment = fragment;
}
public String getLastImageLoadedPath() {
return lastImageLoadedPath;
}
public void saveImageWhenLoaded(boolean saveImageWhenLoaded) {
this.saveImageWhenLoaded = saveImageWhenLoaded;
}
public CircleImageView getProfilePic() {
return profileCircleImageView;
}
public void setProfileUser(BUser profileUser) {
this.profileUser = profileUser;
}
}