package net.osmand.plus.mapillary;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ConsoleMessage;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialog;
import net.osmand.plus.mapcontextmenu.builders.cards.dialogs.ContextMenuCardDialogFragment;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
public class MapillaryImageDialog extends ContextMenuCardDialog {
private static final String KEY_MAPILLARY_DIALOG_IMAGE_KEY = "key_mapillary_dialog_image_key";
private static final String KEY_MAPILLARY_DIALOG_IMAGE_URL = "key_mapillary_dialog_image_url";
private static final String KEY_MAPILLARY_DIALOG_VIEWER_URL = "key_mapillary_dialog_viewer_url";
private static final String KEY_MAPILLARY_DIALOG_LATLON = "key_mapillary_dialog_latlon";
private static final String KEY_MAPILLARY_DIALOG_CA = "key_mapillary_dialog_ca";
private static final String MAPILLARY_VIEWER_URL_TEMPLATE =
"https://osmand.net/api/mapillary/photo-viewer.php?photo_id=";
private static final String MAPILLARY_HIRES_IMAGE_URL_TEMPLATE =
"https://osmand.net/api/mapillary/get_photo.php?hires=true&photo_id=";
private static final String WEBGL_ERROR_MESSAGE = "Error creating WebGL context";
private String key;
private String imageUrl;
private String viewerUrl;
private LatLon latLon;
private double ca = Double.NaN;
public MapillaryImageDialog(@NonNull MapActivity mapActivity, @NonNull Bundle bundle) {
super(mapActivity, CardDialogType.MAPILLARY);
restoreFields(bundle);
}
public MapillaryImageDialog(MapActivity mapActivity, String key, String imageUrl, String viewerUrl, LatLon latLon, double ca,
String title, String description) {
super(mapActivity, CardDialogType.MAPILLARY);
this.title = title;
this.description = description;
this.key = key;
this.imageUrl = imageUrl;
this.viewerUrl = viewerUrl;
this.latLon = latLon;
this.ca = ca;
}
public String getKey() {
return key;
}
public String getViewerUrl() {
return viewerUrl;
}
public LatLon getLatLon() {
return latLon;
}
public double getCa() {
return ca;
}
public void saveMenu(Bundle bundle) {
super.saveMenu(bundle);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_KEY, key);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_IMAGE_URL, imageUrl);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_VIEWER_URL, viewerUrl);
bundle.putSerializable(KEY_MAPILLARY_DIALOG_LATLON, latLon);
bundle.putDouble(KEY_MAPILLARY_DIALOG_CA, ca);
}
@Override
protected void restoreFields(Bundle bundle) {
super.restoreFields(bundle);
this.key = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_KEY);
this.imageUrl = bundle.getString(KEY_MAPILLARY_DIALOG_IMAGE_URL);
this.viewerUrl = bundle.getString(KEY_MAPILLARY_DIALOG_VIEWER_URL);
Object latLonObj = bundle.getSerializable(KEY_MAPILLARY_DIALOG_LATLON);
if (latLonObj != null) {
this.latLon = (LatLon) latLonObj;
}
this.ca = bundle.getDouble(KEY_MAPILLARY_DIALOG_CA, Double.NaN);
}
public void onResume() {
super.onResume();
setImageLocation(latLon, ca, true);
}
public void onPause() {
super.onPause();
setImageLocation(null, Double.NaN, false);
}
private void setImageLocation(LatLon latLon, double ca, boolean animated) {
OsmandMapTileView mapView = getMapActivity().getMapView();
MapillaryLayer layer = mapView.getLayerByClass(MapillaryLayer.class);
if (layer != null) {
layer.setSelectedImageLocation(latLon);
if (!Double.isNaN(ca)) {
layer.setSelectedImageCameraAngle((float) ca);
} else {
layer.setSelectedImageCameraAngle(null);
}
}
if (latLon != null) {
if (animated) {
mapView.getAnimatedDraggingThread().startMoving(
latLon.getLatitude(), latLon.getLongitude(), mapView.getZoom(), true);
} else {
getMapActivity().setMapLocation(latLon.getLatitude(), latLon.getLongitude());
}
} else {
getMapActivity().refreshMap();
}
}
public View getContentView() {
if (getMapActivity().getMyApplication().getSettings().WEBGL_SUPPORTED.get()) {
return getWebView();
} else {
return getStaticImageView();
}
}
@Override
protected boolean haveMenuItems() {
return true;
}
@Override
protected void createMenuItems(Menu menu) {
MenuItem item = menu.add(R.string.open_mapillary)
.setIcon(getMapActivity().getMyApplication().getIconsCache().getThemedIcon(
R.drawable.ic_action_mapillary));
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
MapillaryPlugin.openMapillary(getMapActivity(), key);
return true;
}
});
}
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
private WebView getWebView() {
final WebView webView = new WebView(getMapActivity());
webView.setBackgroundColor(Color.argb(1, 0, 0, 0));
//webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
webView.setScrollContainer(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new MapillaryWebAppInterface(), "Android");
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
isPortrait() ? ViewGroup.LayoutParams.MATCH_PARENT : AndroidUtils.dpToPx(getMapActivity(), 360f),
isPortrait() ? AndroidUtils.dpToPx(getMapActivity(), 270f) : ViewGroup.LayoutParams.MATCH_PARENT);
webView.setLayoutParams(lp);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
if (!Algorithms.isEmpty(consoleMessage.message()) && consoleMessage.message().contains(WEBGL_ERROR_MESSAGE)) {
getMapActivity().getMyApplication().getSettings().WEBGL_SUPPORTED.set(false);
show(getMapActivity(), key, imageUrl, viewerUrl, getLatLon(), getCa(), getTitle(), getDescription());
}
return false;
}
});
webView.loadUrl(viewerUrl);
return webView;
}
private class MapillaryWebAppInterface {
@JavascriptInterface
public void onNodeChanged(double latitude, double longitude, double ca, String key) {
LatLon latLon = null;
if (!Double.isNaN(latitude) && !Double.isNaN(longitude)) {
latLon = new LatLon(latitude, longitude);
MapillaryImageDialog.this.latLon = latLon;
MapillaryImageDialog.this.ca = ca;
if (!Algorithms.isEmpty(key)) {
MapillaryImageDialog.this.key = key;
MapillaryImageDialog.this.imageUrl = MAPILLARY_HIRES_IMAGE_URL_TEMPLATE + key;
MapillaryImageDialog.this.viewerUrl = MAPILLARY_VIEWER_URL_TEMPLATE + key;
}
}
setImageLocation(latLon, ca, false);
}
}
private View getStaticImageView() {
LinearLayout ll = new LinearLayout(getMapActivity());
ll.setClickable(true);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
isPortrait() ? ViewGroup.LayoutParams.MATCH_PARENT : AndroidUtils.dpToPx(getMapActivity(), 360f),
isPortrait() ? AndroidUtils.dpToPx(getMapActivity(), 270f) : ViewGroup.LayoutParams.MATCH_PARENT);
ll.setGravity(Gravity.CENTER);
ll.setLayoutParams(lp);
ProgressBar progressBar = new ProgressBar(getMapActivity());
progressBar.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
ll.addView(progressBar);
ImageView imageView = new ImageView(getMapActivity());
imageView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ll.addView(imageView);
if (!Algorithms.isEmpty(imageUrl)) {
MenuBuilder.execute(new DownloadImageTask(progressBar, imageView));
}
return ll;
}
public static MapillaryImageDialog show(MapActivity mapActivity, String key, String imageUrl,
String viewerUrl, LatLon latLon, double ca,
String title, String description) {
MapillaryImageDialog dialog = new MapillaryImageDialog(mapActivity, key, imageUrl, viewerUrl,
latLon, ca, title, description);
ContextMenuCardDialogFragment.showInstance(dialog);
return dialog;
}
private class DownloadImageTask extends AsyncTask<Void, Void, Bitmap> {
private ProgressBar progressBar;
private ImageView imageView;
public DownloadImageTask(ProgressBar progressBar, ImageView imageView) {
this.progressBar = progressBar;
this.imageView = imageView;
}
@Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected Bitmap doInBackground(Void... params) {
return AndroidNetworkUtils.downloadImage(getMapActivity().getMyApplication(), imageUrl);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
progressBar.setVisibility(View.GONE);
if (bitmap != null) {
imageView.setImageDrawable(new BitmapDrawable(getMapActivity().getResources(), bitmap));
}
}
}
}