/** ************************************************* */
  @Override
  public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    Bundle extras = getIntent().getExtras();

    String findLoc = null;
    if (extras != null) {

      findLoc = extras.getString(KEY_LOCATION);

      // used by Events:
      if (extras.containsKey(KEY_LON) && extras.containsKey(KEY_LAT)) {
        int lon, lat;
        lon = extras.getInt(KEY_LON);
        lat = extras.getInt(KEY_LAT);
        ev_gpt = new GeoPoint(lon, lat);
      }

      if (ev_gpt != null) {
        mMapItems = new ArrayList<MapItem>();
        MapItem m = new MapItem();
        m.name = title;
        m.snippets = snippet;
        mMapItems.add(m);
      }

      if (module != null && module.equals(MODULE_SHUTTLE)) {
        mRouteItem = extras.getParcelable(KEY_ROUTE);
      }
    }

    // Four cases:
    //
    // 1 - Events sends LAT/LON
    // 2 - Stellar sends findLoc query that should yield ONE building
    // 3 - Map Search sends many buildings
    // 4 - Shuttle sends many stops

    center = new GeoPoint(42359238, -71093109); // MIT

    mListView = (ListView) findViewById(R.id.mapListView);

    TitleBar titleBar = (TitleBar) findViewById(R.id.mapTitleBar);
    if (module != null) {
      if (module.equals(MODULE_SHUTTLE)) {
        titleBar.setTitle("Route Map");
      }
    } else {
      titleBar.setTitle("Campus Map");
    }

    if (findLoc == null) {
      if (mMapItems == null) {

        mMapItems = loadMapItems(getIntent()); // passed from Browse or Search?
        if (mMapItems == null) {
          mMapItems = new ArrayList<MapItem>(); // empty ok
        }
      }
      setOverlays();
    } else {
      doSearch(findLoc);
    }
  }
 @Override
 public void onDestroy() {
   super.onDestroy();
   if (mut != null) mut.cancel(true);
 }
 /** ************************************************* */
 @Override
 public void onResume() {
   super.onResume();
   if (mut != null) mut.pause = false;
   // if (mut!=null) mut.notify();
 }
 @Override
 public void onPause() {
   super.onPause();
   // if (mut!=null) mut.cancel(true); // would need to recreate in onResume()
   if (mut != null) mut.pause = true; // TODO maybe wait()
 }
  /** ************************************************* */
  @Override
  protected void setOverlays() {

    super.setOverlays();

    if (markers != null) {
      mapView.removeAllViews();
      ovrlys.remove(markers);
    }

    int size = 0;

    // Building or Shuttle?
    if (MODULE_SHUTTLE.equals(module)) {

      setTitle("Shuttles Map");

      if (mut != null) mut.cancel(true);

      mut = new MITMapShuttlesUpdaterTask(ctx, mapView, mRouteItem);

      RoutesParser rp = new RoutesParser();
      mut.execute(rp.getBaseUrl() + "?command=routeInfo&full=true", null, null);

      markers = mut.stopsMarkers;

      size = markers.size();

    } else {

      Drawable pin;
      GeoPoint gpt;

      // handles Events, Map search, and Stellar...

      pin = this.getResources().getDrawable(R.drawable.map_red_pin);
      markers = new MITItemizedOverlay(pin, this, mapView);

      // Convert MapItem to PinItems
      int lat, lon;
      String title, name;
      for (MapItem m : mMapItems) {
        lat = (int) (m.lat_wgs84 * 1000000.0);
        lon = (int) (m.long_wgs84 * 1000000.0);
        gpt = new GeoPoint(lat, lon);

        if ("".equals(m.bldgnum)) title = m.name;
        else title = "Building " + m.bldgnum;

        if (title.equals(m.name)) name = "";
        else name = m.name;

        PinItem p = new PinItem(gpt, title, name, m);
        markers.addOverlay(p);
      }

      size = markers.size();

      if (size > 0) ovrlys.add(markers);
    }

    // Show balloon if single item or direct from shuttle stop details view
    if (size == 1) {
      PinItem p = (PinItem) markers.getItem(0);
      markers.makeBalloon(p);
    } else if (bubble_pos > -1) {
      PinItem p = (PinItem) markers.getItem(bubble_pos);
      markers.makeBalloon(p);
    }

    // Try to center map...
    if (size > 1) {
      int latSpanE6 = 10000;
      int lonSpanE6 = 10000;
      // #1 TODO? seems unreliable (only computes after rendered?)
      // center = markers.getCenter();
      // int latSpan = markers.getLatSpanE6();
      // int lonSpan = markers.getLonSpanE6();
      // #2
      PinItem p = (PinItem) markers.getItem(0);
      GeoPoint g = p.getPoint();
      int maxLat = g.getLatitudeE6();
      int minLat = maxLat;
      int maxLon = g.getLongitudeE6();
      int minLon = maxLon;
      int lat, lon;
      for (int x = 1; x < size; x++) {
        p = (PinItem) markers.getItem(x);
        g = p.getPoint();
        lat = g.getLatitudeE6();
        lon = g.getLongitudeE6();
        if (lat < minLat) minLat = lat;
        if (lat > maxLat) maxLat = lat;
        if (lon < minLon) minLon = lon;
        if (lon > maxLon) maxLon = lon;
      }
      lat = (maxLat - minLat) / 2 + minLat;
      lon = (maxLon - minLon) / 2 + minLon;
      center = new GeoPoint(lat, lon);
      mctrl.setCenter(center);
      if (maxLat - minLat > 0) latSpanE6 = maxLat - minLat;
      if (maxLon - minLon > 0) lonSpanE6 = maxLon - minLon;
      // mctrl.zoomToSpan(latSpanE6, lonSpanE6);
      final int latSpan = (int) (latSpanE6 * 0.90);
      final int lonSpan = (int) (lonSpanE6 * 0.90);
      mapView.post(
          new Runnable() {
            @Override
            public void run() {
              // MapView ignores following unless using post() (needs to render first)
              mctrl.zoomToSpan(latSpan, lonSpan);
              int z = mapView.getZoomLevel();
              if (z < 15) {
                mctrl.setZoom(15);
              }
            }
          });

    } else if (size == 1) {
      mctrl.setCenter(center);
      mapView.post(
          new Runnable() {
            @Override
            public void run() {
              // MapView ignores following unless using post() (needs to render first)
              mctrl.setZoom(INIT_ZOOM_ONE_ITEM);
            }
          });
    } else {

      // Initial zoom out
      mctrl.setCenter(center);
      mapView.post(
          new Runnable() {
            @Override
            public void run() {
              mctrl.setZoom(INIT_ZOOM_ONE_ITEM);
            }
          });

      myLocationOverlay.snapFirstTime = true;
    }
  }