/*
* Copyright 2011 Austin Wagner
*
* This file is part of Mobile Shuttle Tracker.
*
* Mobile Shuttle Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Mobile Shuttle Tracker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mobile Shuttle Tracker. If not, see <http://www.gnu.org/licenses/>.
*/
package com.abstractedsheep.shuttletracker.mapoverlay;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import android.app.LauncherActivity;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import com.abstractedsheep.shuttletracker.TrackerPreferences;
import com.abstractedsheep.shuttletrackerworld.Route;
import com.abstractedsheep.shuttletrackerworld.Shuttle;
import com.abstractedsheep.shuttletrackerworld.World;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.readystatesoftware.mapviewballoons.BalloonItemizedOverlay;
import com.readystatesoftware.mapviewballoons.BalloonOverlayView;
public class ShuttleItemizedOverlay extends BalloonItemizedOverlay<DirectionalOverlayItem> {
private static final int MAGENTA = Color.rgb(255, 0, 255);
private final Bitmap markerBitmap;
private final Bitmap markerBitmapFlipped;
private final HashMap<Integer, Bitmap> coloredMarkers = new HashMap<Integer, Bitmap>();
private final HashMap<Integer, Bitmap> coloredMarkersFlipped = new HashMap<Integer, Bitmap>();
private final BiMap<Integer, Integer> idToIndex = HashBiMap.create();
private int visibleBalloon = -1;
private final World world;
private boolean visible = true;
private final List<Shuttle> shuttles = new ArrayList<Shuttle>();
private final SimpleDateFormat formatter12 = new SimpleDateFormat("MM/dd/yy h:mm:ss a");
private final SimpleDateFormat formatter24 = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
private final SharedPreferences prefs;
public ShuttleItemizedOverlay(Drawable defaultMarker, MapView map, World world, SharedPreferences prefs) {
super(boundCenter(defaultMarker), map);
this.world = world;
this.prefs = prefs;
shuttlesUpdated();
Matrix flip = new Matrix();
flip.reset();
flip.setScale(-1.0f, 1.0f);
markerBitmap = ((BitmapDrawable) boundCenter(defaultMarker)).getBitmap();
markerBitmapFlipped = Bitmap.createBitmap(markerBitmap, 0, 0, markerBitmap.getWidth(), markerBitmap.getHeight(), flip, true);
generateColoredMarkers();
}
@Override
protected boolean onTap(int index) {
visibleBalloon = idToIndex.inverse().get(index);
long now = (new Date()).getTime();
Date lastUpdate = new Date(shuttles.get(index).getLastUpdateTime());
return (now - lastUpdate.getTime()) >= 45000 || super.onTap(index);
}
@Override
public void hideBalloon() {
visibleBalloon = -1;
super.hideBalloon();
}
public void hide() {
visible = false;
}
public void show() {
visible = true;
}
public void shuttlesUpdated() {
this.shuttles.clear();
this.shuttles.addAll(world.getShuttleList());
populate();
BalloonOverlayView balloonView = getBalloonView();
Integer vehicleId = idToIndex.get(visibleBalloon);
if (balloonView != null && balloonView.isVisible() && vehicleId != null) {
OverlayItem oi = getItem(vehicleId);
balloonView.setData(oi);
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, oi.getPoint(),
MapView.LayoutParams.BOTTOM_CENTER);
params.mode = MapView.LayoutParams.MODE_MAP;
balloonView.setVisibility(View.VISIBLE);
balloonView.setLayoutParams(params);
} else if (balloonView != null && balloonView.isVisible() && vehicleId == null) {
hideBalloon();
}
}
@Override
protected synchronized DirectionalOverlayItem createItem(int i) {
Shuttle s = shuttles.get(i);
GeoPoint gp = new GeoPoint(s.getSnappedCoordinate().getLatitudeE6(), s.getSnappedCoordinate().getLongitudeE6());
String updateTime;
if (prefs.getBoolean(TrackerPreferences.USE_24_HOUR, false)) {
updateTime = "Last Updated at\n" + formatter24.format(new Date(s.getLastUpdateTime()));
} else {
updateTime = "Last Updated at\n" + formatter12.format(new Date(s.getLastUpdateTime()));
}
return new DirectionalOverlayItem(gp, s.getBearing(), s.getName(), updateTime);
}
@Override
public int size() {
return shuttles.size();
}
@Override
public synchronized void draw(Canvas canvas, MapView mapView, boolean shadow) {
if (!visible) return;
final Projection p = mapView.getProjection();
final Matrix rotate = new Matrix();
long now = (new Date()).getTime();
for (Shuttle s : shuttles) {
Date lastUpdate = new Date(s.getLastUpdateTime());
long age = now - lastUpdate.getTime();
if (age > 45000)
continue;
GeoPoint gp = new GeoPoint(s.getLocation().getLatitudeE6(), s.getLocation().getLongitudeE6());
Point pt = p.toPixels(gp, null);
rotate.reset();
Bitmap tempBitmap;
if (s.getBearing() > 180) {
tempBitmap = coloredMarkersFlipped.get(s.getCurrentRoute().getId());
rotate.postRotate(s.getBearing(), tempBitmap.getWidth() / 2, tempBitmap.getHeight() / 2);
tempBitmap = Bitmap.createBitmap(tempBitmap, 0, 0, tempBitmap.getWidth(), tempBitmap.getHeight(), rotate, true);
} else {
tempBitmap = coloredMarkers.get(s.getCurrentRoute().getId());
rotate.postRotate(s.getBearing(), tempBitmap.getWidth() / 2, tempBitmap.getHeight() / 2);
tempBitmap = Bitmap.createBitmap(tempBitmap, 0, 0, tempBitmap.getWidth(), tempBitmap.getHeight(), rotate, true);
}
canvas.drawBitmap(tempBitmap, pt.x - (tempBitmap.getWidth() / 2), pt.y - (tempBitmap.getHeight() / 2), null);
}
}
private void generateColoredMarkers() {
for (Route r : world.getRouteList()) {
coloredMarkers.put(r.getId(), recolorBitmap(markerBitmap, r.getColor()));
coloredMarkersFlipped.put(r.getId(), recolorBitmap(markerBitmapFlipped, r.getColor()));
}
}
private Bitmap recolorBitmap(Bitmap bitmap, int color) {
Bitmap b = bitmap.copy(Config.ARGB_8888, true);
for (int i = 0; i < b.getWidth(); i++) {
for (int j = 0; j < b.getHeight(); j++) {
if (b.getPixel(i, j) == MAGENTA)
b.setPixel(i, j, color);
}
}
return b;
}
}