package mil.nga.giat.mage.profile;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mil.nga.giat.mage.R;
import mil.nga.giat.mage.map.marker.LocationBitmapFactory;
import mil.nga.giat.mage.sdk.datastore.location.Location;
import mil.nga.giat.mage.sdk.datastore.location.LocationHelper;
import mil.nga.giat.mage.sdk.datastore.user.User;
import mil.nga.giat.mage.sdk.datastore.user.UserHelper;
import mil.nga.giat.mage.sdk.datastore.user.UserLocal;
import mil.nga.giat.mage.sdk.exceptions.UserException;
import mil.nga.giat.mage.sdk.fetch.DownloadImageTask;
import mil.nga.giat.mage.sdk.profile.UpdateProfileTask;
import mil.nga.giat.mage.sdk.utils.MediaUtility;
public class ProfileFragment extends Fragment implements OnMapReadyCallback, View.OnClickListener {
private static final String LOG_NAME = ProfileFragment.class.getName();
private static final String CURRENT_MEDIA_PATH = "CURRENT_MEDIA_PATH";
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int GALLERY_ACTIVITY_REQUEST_CODE = 200;
private static final int PERMISSIONS_REQUEST_CAMERA = 300;
private static final int PERMISSIONS_REQUEST_STORAGE = 400;
public static String USER_ID = "USER_ID";
private String currentMediaPath;
private User user;
private MapView mapView;
private LatLng latLng = new LatLng(0, 0);
private float zoom = 0f;
private BitmapDescriptor icon;
@Override
public void onDestroy() {
mapView.onDestroy();
super.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_profile, container, false);
if (savedInstanceState != null) {
currentMediaPath = savedInstanceState.getParcelable(CURRENT_MEDIA_PATH);
}
final Context context = getActivity().getApplicationContext();
String userToLoad = getActivity().getIntent().getStringExtra(USER_ID);
User currentUser = null;
try {
currentUser = UserHelper.getInstance(context).readCurrentUser();
if (userToLoad != null) {
user = UserHelper.getInstance(context).read(userToLoad);
} else {
user = UserHelper.getInstance(context).readCurrentUser();
}
List<Location> lastLocation = LocationHelper.getInstance(context).getUserLocations(user.getId(), getActivity(), 1, true);
if (!lastLocation.isEmpty()) {
Geometry geo = lastLocation.get(0).getGeometry();
if (geo instanceof Point) {
Point point = (Point) geo;
latLng = new LatLng(point.getY(), point.getX());
icon = LocationBitmapFactory.bitmapDescriptor(context, lastLocation.get(0), user);
}
}
} catch (UserException ue) {
Log.e(LOG_NAME, "Problem finding user.", ue);
}
MapsInitializer.initialize(context);
mapView = (MapView) rootView.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
final String displayName = user.getDisplayName();
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
actionBar.setTitle(user.equals(currentUser) ? "My Profile" : displayName);
actionBar.setSubtitle(null);
setHasOptionsMenu(true);
final TextView realNameTextView = (TextView)rootView.findViewById(R.id.realName);
realNameTextView.setText(displayName);
final TextView phoneTextView = (TextView)rootView.findViewById(R.id.phone);
rootView.findViewById(R.id.profile_picture).setOnClickListener(this);
if (StringUtils.isNotBlank(user.getPrimaryPhone())) {
SpannableString primaryPhone = new SpannableString(user.getPrimaryPhone());
primaryPhone.setSpan(new UnderlineSpan(), 0, primaryPhone.length(), 0);
phoneTextView.setText(primaryPhone);
phoneTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(context);
mBuilder.setMessage("Do you want to call or text " + displayName + "?");
mBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
mBuilder.setNeutralButton("Call", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + phoneTextView.getText().toString()));
startActivity(callIntent);
} catch (ActivityNotFoundException ae) {
Toast.makeText(getActivity(), "Could not call user.", Toast.LENGTH_SHORT).show();
Log.e(LOG_NAME, "Could not call user.", ae);
}
}
});
mBuilder.setPositiveButton("Text", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent textIntent = new Intent(Intent.ACTION_VIEW, Uri.fromParts("sms", phoneTextView.getText().toString(), null));
startActivity(textIntent);
}
});
mBuilder.create().show();
}
});
phoneTextView.setVisibility(View.VISIBLE);
} else {
phoneTextView.setVisibility(View.GONE);
}
final TextView emailTextView = (TextView)rootView.findViewById(R.id.email);
if (StringUtils.isNotBlank(user.getEmail())) {
SpannableString emailAddress = new SpannableString(user.getEmail());
emailAddress.setSpan(new UnderlineSpan(), 0, emailAddress.length(), 0);
emailTextView.setText(emailAddress);
emailTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(context);
mBuilder.setMessage("Do you want to email " + displayName + "?");
mBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
mBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("message/rfc822");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{emailTextView.getText().toString()});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "MAGE");
try {
startActivity(Intent.createChooser(emailIntent, "Send mail..."));
} catch (ActivityNotFoundException ae) {
Toast.makeText(getActivity(), "There are no email clients installed.", Toast.LENGTH_SHORT).show();
Log.e(LOG_NAME, "Could not email user.", ae);
}
}
});
mBuilder.create().show();
}
});
emailTextView.setVisibility(View.VISIBLE);
} else {
emailTextView.setVisibility(View.GONE);
}
final ImageView imageView = (ImageView)rootView.findViewById(R.id.profile_picture);
String avatarUrl = user.getAvatarUrl();
String localAvatarPath = user.getUserLocal().getLocalAvatarPath();
if(StringUtils.isNotBlank(localAvatarPath)) {
Glide.with(context)
.load(localAvatarPath)
.asBitmap()
.centerCrop()
.into(new BitmapImageViewTarget(imageView) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);
circularBitmapDrawable.setCircular(true);
imageView.setImageDrawable(circularBitmapDrawable);
}
});
} else {
if (avatarUrl != null) {
new DownloadImageTask(context, Collections.singletonList(user), DownloadImageTask.ImageType.AVATAR, false, new DownloadImageTask.OnImageDownloadListener() {
@Override
public void complete() {
try {
user = UserHelper.getInstance(context).read(user.getId());
UserLocal userLocal = user.getUserLocal();
if (userLocal.getLocalAvatarPath() != null) {
Glide.with(context)
.load(userLocal.getLocalAvatarPath())
.asBitmap()
.centerCrop()
.into(new BitmapImageViewTarget(imageView) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);
circularBitmapDrawable.setCircular(true);
imageView.setImageDrawable(circularBitmapDrawable);
}
});
}
} catch (UserException e) {
}
}
}).execute();
}
}
return rootView;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.profile_picture:
onAvatarClick();
break;
}
}
private void onAvatarClick() {
final Context context = getActivity().getApplicationContext();
try {
if (user.getId().equals(UserHelper.getInstance(context).readCurrentUser().getId())) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setItems(R.array.profileImageChoices, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0: {
Intent intent = new Intent(context, ProfilePictureViewerActivity.class);
intent.putExtra(ProfilePictureViewerActivity.USER_ID, user.getId());
startActivity(intent);
break;
}
case 1: {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_STORAGE);
} else {
launchGalleryIntent();
}
break;
}
case 2: {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_CAMERA);
} else {
launchCameraIntent();
}
break;
}
}
}
});
builder.create().show();
} else {
final Intent intent = new Intent(context, ProfilePictureViewerActivity.class);
intent.putExtra(ProfilePictureViewerActivity.USER_ID, user.getId());
startActivityForResult(intent, 1);
}
} catch (Exception e) {
Log.e(LOG_NAME, "Problem setting profile picture.");
}
}
private void launchCameraIntent() {
try {
File file = MediaUtility.createImageFile();
currentMediaPath = file.getAbsolutePath();
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
} catch (IOException e) {
Log.e(LOG_NAME, "Error creating video media file", e);
}
}
private void launchGalleryIntent() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
Log.i(LOG_NAME, "build version sdk int: " + Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
startActivityForResult(intent, GALLERY_ACTIVITY_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_REQUEST_CAMERA: {
Map<String, Integer> grants = new HashMap<String, Integer>();
grants.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
grants.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
for (int i = 0; i < grantResults.length; i++) {
grants.put(permissions[i], grantResults[i]);
}
if (grants.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
grants.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
launchCameraIntent();
} else if ((!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) && grants.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) ||
(!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE) && grants.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) ||
!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) && !shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// User denied camera or storage with never ask again. Since they will get here
// by clicking the camera button give them a dialog that will
// guide them to settings if they want to enable the permission
showDisabledPermissionsDialog(
getResources().getString(R.string.camera_access_title),
getResources().getString(R.string.camera_access_message));
}
break;
}
case PERMISSIONS_REQUEST_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
launchGalleryIntent();
} else {
if (!shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
// User denied storage with never ask again. Since they will get here
// by clicking the gallery button give them a dialog that will
// guide them to settings if they want to enable the permission
showDisabledPermissionsDialog(
getResources().getString(R.string.gallery_access_title),
getResources().getString(R.string.gallery_access_message));
}
}
break;
}
}
}
private void showDisabledPermissionsDialog(String title, String message) {
new AlertDialog.Builder(getActivity(), R.style.AppCompatAlertDialogStyle)
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.settings, new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getActivity().getApplicationContext().getPackageName(), null));
startActivity(intent);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
@Override
public void onMapReady(GoogleMap map) {
if (latLng != null && icon != null) {
map.addMarker(new MarkerOptions()
.position(latLng)
.icon(icon));
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
}
}
private void setProfilePicture(File file, ImageView imageView) {
if (file.exists() && file.canRead()) {
try {
imageView.setImageBitmap(MediaUtility.resizeAndRoundCorners(BitmapFactory.decodeStream(new FileInputStream(file)), 150));
} catch(Exception e) {
Log.e(LOG_NAME, "Problem setting profile picture.");
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != AppCompatActivity.RESULT_OK) {
return;
}
String filePath = null;
switch (requestCode) {
case CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE:
filePath = currentMediaPath;
File file = new File(currentMediaPath);
MediaUtility.addImageToGallery(getActivity().getApplicationContext(), Uri.fromFile(file));
break;
case GALLERY_ACTIVITY_REQUEST_CODE:
List<Uri> uris = getUris(data);
for (Uri uri : uris) {
try {
File avatarFile = MediaUtility.copyMediaFromUri(getActivity(),uri);
filePath = avatarFile.getAbsolutePath();
} catch (IOException e) {
Log.e(LOG_NAME, "Error copying gallery file for avatar to local storage", e);
}
}
break;
}
if (filePath != null) {
final Context context = getActivity().getApplicationContext();
final ImageView iv = (ImageView) getActivity().findViewById(R.id.profile_picture);
Glide.with(context).load(filePath).centerCrop().into(iv);
Glide.with(context)
.load(filePath)
.asBitmap()
.fallback(R.id.profile_picture)
.centerCrop()
.into(new BitmapImageViewTarget(iv) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);
circularBitmapDrawable.setCircular(true);
iv.setImageDrawable(circularBitmapDrawable);
}
});
try {
UserHelper.getInstance(context).setAvatarPath(user, filePath);
} catch (UserException e) {
Log.e(LOG_NAME, "Error setting local avatar path", e);
}
UpdateProfileTask task = new UpdateProfileTask(user, getActivity());
task.execute(filePath);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CURRENT_MEDIA_PATH, currentMediaPath);
}
private List<Uri> getUris(Intent intent) {
List<Uri> uris = new ArrayList<Uri>();
uris.addAll(getClipDataUris(intent));
if (intent.getData() != null) {
uris.add(intent.getData());
}
return uris;
}
@TargetApi(16)
private List<Uri> getClipDataUris(Intent intent) {
List<Uri> uris = new ArrayList<Uri>();
if (Build.VERSION.SDK_INT >= 16) {
ClipData cd = intent.getClipData();
if (cd != null) {
for (int i = 0; i < cd.getItemCount(); i++) {
uris.add(cd.getItemAt(i).getUri());
}
}
}
return uris;
}
}