package com.lake.tahoe.activities; import android.location.Location; import android.os.Bundle; import android.view.View; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.lake.tahoe.R; import com.lake.tahoe.callbacks.ModelCallback; import com.lake.tahoe.handlers.RequestUpdateChannel; import com.lake.tahoe.handlers.UserUpdateChannel; import com.lake.tahoe.models.Request; import com.lake.tahoe.models.User; import com.lake.tahoe.utils.ActivityUtil; import com.lake.tahoe.utils.MapUtil; import com.lake.tahoe.utils.PushUtil; import com.lake.tahoe.views.DynamicActionBar; import com.lake.tahoe.widgets.SpeechBubble; import com.lake.tahoe.widgets.SpeechBubbleIconGenerator; import com.parse.ParsePush; import com.parse.ParseUser; import java.util.Hashtable; public class RequestMapActivity extends GoogleLocationServiceActivity implements RequestUpdateChannel.HandlesRequestUpdates, UserUpdateChannel.HandlesUserUpdates, PushUtil.HandlesPublish, ModelCallback<Request> { GoogleMap map; Marker marker; DynamicActionBar actionBar; Hashtable<Marker, Request> markerRequestMap = new Hashtable<Marker, Request>(); Hashtable<String, Marker> userMarkerMap = new Hashtable<String, Marker>(); SpeechBubbleIconGenerator iconGenerator = new SpeechBubbleIconGenerator(this); boolean mapReadyToPan = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_request_map); actionBar = new DynamicActionBar(this); actionBar.setLeftAction(R.drawable.ic_action_client_mode, new View.OnClickListener() { @Override public void onClick(View v) { convertToClient(); } }); setUpActionBar(); } public void setUpActionBar() { actionBar.setTitle(getResources().getString(R.string.select_client)); actionBar.setBackgroundColor(getResources().getColor(R.color.black)); actionBar.toggleLeftAction(View.VISIBLE); actionBar.toggleRightAction(View.INVISIBLE); } private void convertToClient() { User user = User.getCurrentUser(); user.setType(User.Type.CLIENT); toggleBlocker(true); user.saveAndPublish(this); } @Override public void onPublished(ParsePush push) { ActivityUtil.startRequestCreateActivity(this); ActivityUtil.transitionFade(this); } @Override public void onRequestUpdated(Request request) { if (request == null) return; if (!request.getState().equals(Request.State.OPEN)) return; generateMarkerForRequest(request); } @Override public void onRequestUpdateError(Throwable t) { onError(t); } @Override public void onModelFound(Request request) { generateMarkerForRequest(request); } void generateMarkerForRequest(Request request) { User client = request.getClient(); if (client == null) { this.onError(new IllegalStateException("Client was null")); return; } String clientId = client.getObjectId(); Marker marker = userMarkerMap.get(clientId); if (marker != null) { marker.setPosition(request.getGoogleMapsLocation()); } else { marker = map.addMarker(MapUtil.getSpeechBubbleMarkerOptions( request, iconGenerator, SpeechBubble.ColorType.BLACK)); } userMarkerMap.put(clientId, marker); markerRequestMap.put(marker, request); } @Override public void onModelError(Throwable e) { // ignore requests if we can't load the details } @Override protected void onStart() { super.onStart(); RequestUpdateChannel.subscribe(this); UserUpdateChannel.subscribe(this); } @Override protected void onStop() { super.onStop(); RequestUpdateChannel.unsubscribe(this); UserUpdateChannel.unsubscribe(this); } @Override public void onUserUpdated(User user) { if (user == null) return; if (user.getObjectId().equals(User.getCurrentUser().getObjectId())) return; if (!user.getType().equals(User.Type.CLIENT)) return; user.getUnfinishedRequest(this); } @Override public void onUserUpdateError(Throwable t) { onError(t); } @Override protected void onGooglePlayServicesReady() { SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); map = fragment.getMap(); map.setOnMarkerClickListener(new OnMarkerClick()); map.setOnMapClickListener(new OnMapClick()); User user = (User) ParseUser.getCurrentUser(); Request.findNearbyRequests(Request.State.OPEN, user, this); mapReadyToPan = true; } /** * TODO We should probably encapsulate this behavior in other classes that use a map. * See the comment on OnMarkerClick (below) about GoogleMapActivity */ @Override public void onLocationChanged(Location location) { super.onLocationChanged(location); LatLng position = MapUtil.locationToLatLng(location); if (mapReadyToPan) { mapReadyToPan = false; MapUtil.panAndZoomToLocation(map, location, MapUtil.DEFAULT_ZOOM_LEVEL); marker = map.addMarker(MapUtil.getSpeechBubbleMarkerOptions(position, getResources().getString(R.string.you), iconGenerator, SpeechBubble.ColorType.PURPLE)); } else if (marker != null && !marker.getPosition().equals(position)) { marker.setPosition(position); } } private class OnMarkerClick implements GoogleMap.OnMarkerClickListener { @Override public boolean onMarkerClick(Marker marker) { final Request request = markerRequestMap.get(marker); if (request == null) return true; BitmapDescriptor bitmapDescriptor = SpeechBubble.generateMarkerBitmap( iconGenerator, request.getDisplayDollars(), SpeechBubble.ColorType.BLUE ); marker.setIcon(bitmapDescriptor); actionBar.setTitle(request.getDisplayDollars() + " | " + request.getTitle()); actionBar.setBackgroundColor(getResources().getColor(R.color.dark_blue)); actionBar.setRightArrowAction(new View.OnClickListener() { @Override public void onClick(View v) { ActivityUtil.startRequestDetailActivity( RequestMapActivity.this, request ); } }); actionBar.toggleLeftAction(View.INVISIBLE); actionBar.toggleRightAction(View.VISIBLE); return true; } } private class OnMapClick implements GoogleMap.OnMapClickListener { @Override public void onMapClick(LatLng point) { setUpActionBar(); } } @Override protected void onGooglePlayServicesError(Throwable t) { onError(t); } @Override protected void onLocationTrackingFailed(Throwable t) { onError(t); } }