/*
* Licensed Materials - Property of IBM
* © Copyright IBM Corporation 2015. All Rights Reserved.
*/
package com.ibm.mil.readyapps.telco.hotspots;
import android.graphics.Point;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.ibm.mil.readyapps.telco.R;
import com.ibm.mil.readyapps.telco.analytics.GestureListener;
import com.ibm.mil.readyapps.telco.utils.JsonUtils;
import com.ibm.mil.readyapps.telco.utils.MapUtils;
import com.ibm.mil.readyapps.telco.utils.RxUtils;
import com.ibm.mil.readyapps.telco.utils.Utils;
import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;
import butterknife.ButterKnife;
import butterknife.Bind;
import butterknife.OnClick;
import rx.Observable;
import rx.functions.Action1;
import rx.subjects.PublishSubject;
public class HotSpotActivity extends AppCompatActivity implements HotSpotView, OnMapReadyCallback {
private static final LatLng DEFAULT_LOCATION = new LatLng(30.398974, -97.712885);
private static final DecimalFormat distanceFormatter = new DecimalFormat("0.0");
private GestureDetectorCompat detector;
@Bind(R.id.toolbar) Toolbar toolbar;
@Bind(R.id.nested_scroll_view) NestedScrollView nestedScrollView;
@Bind(R.id.map_area) View mapArea;
@Bind(R.id.map_touchevent_capture_view) View mapTouchEventCaptureView;
@Bind(R.id.content_area) View contentArea;
@Bind(R.id.progress_bar) CircleProgressBar progressBar;
@Bind(R.id.fab) FloatingActionButton fab;
@Bind(R.id.hotspot_name) TextView hotSpotName;
@Bind(R.id.verification_status) TextView verificationStatus;
@Bind(R.id.hotspot_distance) TextView hotspotDistance;
@Bind(R.id.address_line1) TextView addressLine1;
@Bind(R.id.address_line2) TextView addressLine2;
@Bind(R.id.download_speed) TextView downloadSpeed;
@Bind(R.id.sign_in_requirement) TextView signInRequirement;
@Bind(R.id.connection_count) TextView connectionCount;
private GoogleMap map;
private HotSpot currentHotSpot;
private Marker currentMarker;
private Marker userMarker;
private HotSpotPresenter presenter;
private BitmapDescriptor activePin;
private BitmapDescriptor defaultPin;
private static SpannableString spanSuffix(String text, String suffix, Object... spans) {
String fullText = text + " " + suffix;
int startIndex = fullText.indexOf(suffix);
int endIndex = fullText.length();
return createSpan(fullText, startIndex, endIndex, spans);
}
private static SpannableString createSpan(String text, int start, int stop, Object... spans) {
SpannableString spannableString = new SpannableString(text);
for (Object span : spans) {
spannableString.setSpan(span, start, stop, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hot_spot);
ButterKnife.bind(this);
detector = new GestureDetectorCompat(this, new GestureListener());
presenter = new HotSpotPresenterImpl(this, new HotSpotModelImpl());
setSupportActionBar(toolbar);
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
progressBar.setColorSchemeColors(R.color.dark_indigo);
// make map area 1/3 of available screen size
Point screenSize = new Point();
getWindowManager().getDefaultDisplay().getSize(screenSize);
mapArea.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
screenSize.y / 3));
// prevent nested scroll view from scrolling up and down when gesture is performed on map
mapTouchEventCaptureView.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
nestedScrollView.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap map) {
this.map = map;
activePin = BitmapDescriptorFactory.fromResource(R.drawable.pin);
defaultPin = BitmapDescriptorFactory.fromResource(R.drawable.dot);
map.setMyLocationEnabled(false);
map.getUiSettings().setMyLocationButtonEnabled(false);
map.getUiSettings().setMapToolbarEnabled(false);
map.getUiSettings().setCompassEnabled(false);
// have presenter watch for marker clicks
final PublishSubject<LatLng> markerPublisher = PublishSubject.create();
presenter.watchMarkerClick(markerPublisher);
map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override public boolean onMarkerClick(Marker marker) {
// define no behavior for clicking user marker
if (marker.getPosition().equals(userMarker.getPosition())) {
return true;
}
// notify subscriber (presenter) that a new marker was selected
// this will cause the presenter to fetch the detailed data for the hotspot
markerPublisher.onNext(marker.getPosition());
// reset marker icon to dot
if (currentMarker != null) {
currentMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.dot));
currentMarker.setAnchor(0.5f, 0.5f);
}
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.pin));
marker.setAnchor(0.5f, 1.0f);
currentMarker = marker;
return false;
}
});
Location userLocation = initUserMarker();
if (Utils.isConnected(this)) {
useOnlineMode(userLocation);
} else {
useOfflineMode(userLocation, null);
}
}
private void useOnlineMode(final Location userLocation) {
final Geocoder geocoder = new Geocoder(this, Locale.getDefault());
presenter.getOnlineHotSpots(geocoder, userLocation)
.compose(hotSpotTransformer())
.subscribe(hotSpotOnNext(), new Action1<Throwable>() {
@Override public void call(Throwable throwable) {
useOfflineMode(userLocation, geocoder);
}
});
}
private void useOfflineMode(Location userLocation, Geocoder geocoder) {
String json = JsonUtils.parseJsonFile(this, "offline_hotspots.json");
presenter.getOfflineHotSpots(json, geocoder, userLocation)
.compose(hotSpotTransformer())
.subscribe(hotSpotOnNext());
}
private Observable.Transformer<HotSpot, List<HotSpot>> hotSpotTransformer() {
return new Observable.Transformer<HotSpot, List<HotSpot>>() {
@Override public Observable<List<HotSpot>> call(Observable<HotSpot> observable) {
return observable.toList().compose(RxUtils.<List<HotSpot>>showBackgroundWork());
}
};
}
private Action1<List<HotSpot>> hotSpotOnNext() {
return new Action1<List<HotSpot>>() {
@Override public void call(List<HotSpot> hotSpots) {
displayHotSpots(hotSpots);
}
};
}
private Location initUserMarker() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
LatLng userPosition = DEFAULT_LOCATION; // default if no user location exists
if (userLocation != null) {
userPosition = new LatLng(userLocation.getLatitude(), userLocation.getLongitude());
}
userMarker = map.addMarker(new MarkerOptions()
.position(userPosition)
.anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.person)));
return MapUtils.convertLatLng(userMarker.getPosition());
}
private void displayHotSpots(List<HotSpot> hotSpots) {
for (int i = 0, size = hotSpots.size(); i < size; i++) {
HotSpot hotSpot = hotSpots.get(i);
LatLng location = new LatLng(hotSpot.getLatitude(), hotSpot.getLongitude());
Marker marker = map.addMarker(new MarkerOptions()
.position(location)
.anchor(0.5f, 0.5f)
.icon(defaultPin));
// select first (nearest) hotspot
if (i == 0) {
currentMarker = marker;
currentHotSpot = hotSpot;
showHotSpotDetails(hotSpot);
marker.setIcon(activePin);
marker.setAnchor(0.5f, 1.0f);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 10.0f));
}
}
contentArea.setVisibility(View.VISIBLE);
fab.setVisibility(View.VISIBLE);
}
@Override public void showHotSpotDetails(HotSpot hotSpot) {
currentHotSpot = hotSpot;
hotSpotName.setText(hotSpot.getName());
addressLine1.setText(hotSpot.getAddressLine1());
addressLine2.setText(hotSpot.getAddressLine2());
if (hotSpot.isVerified()) {
verificationStatus.setText(R.string.verified_network);
} else {
verificationStatus.setText(R.string.unverified_network);
}
if (hotSpot.getSignInRequired()) {
signInRequirement.setText(R.string.sign_in);
} else {
signInRequirement.setText(R.string.no_sign_in);
}
downloadSpeed.setText(spanSuffix(Integer.toString(hotSpot.getDownloadSpeed()),
getString(R.string.internet_unit), new RelativeSizeSpan(0.75f)));
connectionCount.setText(spanSuffix(Integer.toString(hotSpot.getConnections()),
getString(R.string.connections), new RelativeSizeSpan(0.75f)));
hotspotDistance.setText(spanSuffix(distanceFormatter.format(hotSpot.getDistanceAway()),
getString(R.string.distance_away), new RelativeSizeSpan(0.66f),
new ForegroundColorSpan(getResources().getColor(R.color.gray_ae))));
}
@OnClick(R.id.fab)
public void getDirections(View view) {
MapUtils.showDirections(this, MapUtils.convertLatLng(userMarker.getPosition()),
MapUtils.convertLatLng(currentHotSpot.getLatitude(), currentHotSpot.getLongitude()));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onTouchEvent(MotionEvent event){
this.detector.onTouchEvent(event);
return super.onTouchEvent(event);
}
}