package net.osmand.plus.parkingpoint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import java.util.List;
/**
* Class represents a layer which depicts the position of the parked car
* @author Alena Fedasenka
* @see ParkingPositionPlugin
*
*/
public class ParkingPositionLayer extends OsmandMapLayer implements
ContextMenuLayer.IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
/**
* magic number so far
*/
private static final int radius = 18;
private DisplayMetrics dm;
private final MapActivity map;
private OsmandMapTileView view;
private Paint bitmapPaint;
private Bitmap parkingNoLimitIcon;
private Bitmap parkingLimitIcon;
private boolean timeLimit;
private ParkingPositionPlugin plugin;
private ContextMenuLayer contextMenuLayer;
public ParkingPositionLayer(MapActivity map, ParkingPositionPlugin plugin) {
this.map = map;
this.plugin = plugin;
}
public LatLon getParkingPoint() {
return plugin.getParkingPosition();
}
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
dm = new DisplayMetrics();
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.getDefaultDisplay().getMetrics(dm);
bitmapPaint = new Paint();
bitmapPaint.setDither(true);
bitmapPaint.setAntiAlias(true);
bitmapPaint.setFilterBitmap(true);
parkingNoLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_no_limit);
parkingLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_limit);
timeLimit = plugin.getParkingType();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
LatLon parkingPoint = getParkingPoint();
boolean inMotion = parkingPoint == contextMenuLayer.getMoveableObject();
if (parkingPoint == null)
return;
Bitmap parkingIcon;
if (!timeLimit) {
parkingIcon = parkingNoLimitIcon;
} else {
parkingIcon = parkingLimitIcon;
}
double latitude = parkingPoint.getLatitude();
double longitude = parkingPoint.getLongitude();
if (isLocationVisible(tileBox, latitude, longitude) || inMotion) {
int marginX = parkingNoLimitIcon.getWidth() / 2;
int marginY = parkingNoLimitIcon.getHeight() / 2;
float locationX;
float locationY;
if (inMotion) {
PointF pf = contextMenuLayer.getMovableCenterPoint(tileBox);
locationX = pf.x;
locationY = pf.y;
} else {
locationX = tileBox.getPixXFromLonNoRot(longitude);
locationY = tileBox.getPixYFromLatNoRot(latitude);
}
canvas.rotate(-view.getRotate(), locationX, locationY);
canvas.drawBitmap(parkingIcon, locationX - marginX, locationY - marginY, bitmapPaint);
}
}
@Override
public void destroyLayer() {
}
@Override
public boolean drawInScreenPixels() {
return false;
}
@Override
public boolean disableSingleTap() {
return false;
}
@Override
public boolean disableLongPressOnMap() {
return false;
}
@Override
public boolean isObjectClickable(Object o) {
return o == getParkingPoint();
}
@Override
public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o) {
getParkingFromPoint(tileBox, point, o);
}
@Override
public LatLon getObjectLocation(Object o) {
if(o == getParkingPoint()) {
return getParkingPoint();
}
return null;
}
public String getFormattedTime(long time){
return plugin.getFormattedTime(time, map);
}
@Override
public PointDescription getObjectName(Object o) {
return new PointDescription(PointDescription.POINT_TYPE_PARKING_MARKER,
view.getContext().getString(R.string.osmand_parking_position_name));
}
public void refresh() {
if (view != null) {
view.refreshMap();
}
}
/**
* @param latitude
* @param longitude
* @return true if the parking point is located on a visible part of map
*/
private boolean isLocationVisible(RotatedTileBox tb, double latitude, double longitude){
if(getParkingPoint() == null || view == null){
return false;
}
return tb.containsLatLon(latitude, longitude);
}
/**
* @param point
* @param parkingPosition
* is in this case not necessarily has to be a list, but it's also used in method
* <link>collectObjectsFromPoint(PointF point, List<Object> o)</link>
*/
private void getParkingFromPoint(RotatedTileBox tb, PointF point, List<? super LatLon> parkingPosition) {
LatLon parkingPoint = getParkingPoint();
if (parkingPoint != null && view != null) {
int ex = (int) point.x;
int ey = (int) point.y;
LatLon position = plugin.getParkingPosition();
int x = (int) tb.getPixXFromLatLon(position.getLatitude(), position.getLongitude());
int y = (int) tb.getPixYFromLatLon(position.getLatitude(), position.getLongitude());
// the width of an image is 40 px, the height is 60 px -> radius = 20,
// the position of a parking point relatively to the icon is at the center of the bottom line of the image
int rad = (int) (radius * tb.getDensity());
if (Math.abs(x - ex) <= rad && (ey - y) <= rad && (y - ey) <= 2.5 * rad) {
parkingPosition.add(parkingPoint);
}
}
}
@Override
public boolean isObjectMovable(Object o) {
return o == getParkingPoint();
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
boolean result = false;
if (o == getParkingPoint()) {
plugin.setParkingPosition(position.getLatitude(), position.getLongitude());
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, getParkingPoint());
}
}
}