package com.robert.maps.applib.overlays;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.andnav.osm.util.GeoPoint;
import org.andnav.osm.util.TypeConverter;
import org.andnav.osm.views.util.StreamUtils;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.location.Location;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import com.robert.maps.applib.R;
import com.robert.maps.applib.utils.CoordFormatter;
import com.robert.maps.applib.utils.DistanceFormatter;
import com.robert.maps.applib.utils.SimpleThreadFactory;
import com.robert.maps.applib.view.MapView;
import com.robert.maps.applib.view.TileView;
import com.robert.maps.applib.view.TileViewOverlay;
public class SearchResultOverlay extends TileViewOverlay {
protected final Paint mPaint = new Paint();
protected final Paint mPaintLine;
protected GeoPoint mLocation;
protected GeoPoint mCurrLocation;
protected String mDescr;
private TextView mT;
private CoordFormatter mCf;
private DistanceFormatter mDf;
//private RequestQueue mRequestQueue;
private double mElevation;
private MapView mMapView;
private boolean mSearchBubble;
private ExecutorService mThreadPool = Executors.newFixedThreadPool(2, new SimpleThreadFactory("SearchResultOverlay"));
private final String LAT;
private final String LON;
private final String ALT;
private final String DIST;
private final String AZIMUT;
public SearchResultOverlay(final Context ctx, MapView mapView) {
this.mDescr = "";
this.mPaint.setAntiAlias(true);
this.mT = (TextView) LayoutInflater.from(ctx).inflate(R.layout.search_bubble, null); //new Button(ctx);
this.mT.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mCf = new CoordFormatter(ctx);
mDf = new DistanceFormatter(ctx);
//mRequestQueue = Volley.newRequestQueue(ctx);
mMapView = mapView;
mPaintLine = new Paint();
mPaintLine.setAntiAlias(true);
mPaintLine.setStrokeWidth(2);
mPaintLine.setStyle(Paint.Style.STROKE);
mPaintLine.setColor(ctx.getResources().getColor(R.color.line_to_gps));
LAT = ctx.getResources().getString(R.string.PoiLat);
LON = ctx.getResources().getString(R.string.PoiLon);
ALT = ctx.getResources().getString(R.string.PoiAlt);
DIST = ctx.getResources().getString(R.string.dist);
AZIMUT = ctx.getResources().getString(R.string.azimuth);
}
@Override
public void Free() {
mThreadPool.shutdown();
super.Free();
}
public void setLocation(final Location loc){
// ������������ ��� ���������� �������� ���������
this.mCurrLocation = TypeConverter.locationToGeoPoint(loc);
if(!mSearchBubble)
setDescr();
}
public void setLocation(final GeoPoint geopoint, final String aDescr){
// ������������ ��� ������
this.mLocation = geopoint;
this.mDescr = aDescr;
mSearchBubble = true;
}
public void Clear(){
this.mLocation = null;
this.mDescr = "";
}
@Override
protected void onDraw(Canvas c, TileView osmv) {
if(this.mLocation != null){
mT.setText(mDescr);
mT.measure(0, 0);
mT.layout(0, 0, mT.getMeasuredWidth(), mT.getMeasuredHeight());
final com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection pj = osmv.getProjection();
final Point screenCoords = new Point();
pj.toPixels(this.mLocation, screenCoords);
if(!mSearchBubble && mCurrLocation != null) {
final Point currLocCoords = new Point();
pj.toPixels(this.mCurrLocation, currLocCoords);
c.drawLine(currLocCoords.x, currLocCoords.y, screenCoords.x, screenCoords.y, mPaintLine);
}
c.save();
c.rotate(osmv.getBearing(), screenCoords.x, screenCoords.y);
c.translate(screenCoords.x - mT.getMeasuredWidth() / 2, screenCoords.y - mT.getMeasuredHeight() + 2);
mT.draw(c);
c.restore();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event,
TileView mapView) {
if (keyCode == KeyEvent.KEYCODE_BACK)
if (mLocation != null) {
mLocation = null;
mapView.invalidate();
return true;
}
return super.onKeyDown(keyCode, event, mapView);
}
@Override
public boolean onSingleTapUp(MotionEvent e, TileView mapView) {
if (mLocation != null) {
final com.robert.maps.applib.view.TileView.OpenStreetMapViewProjection pj = mapView.getProjection();
final Point screenCoords = new Point();
pj.toPixels(this.mLocation, mapView.getBearing(), screenCoords);
final Rect rect = new Rect(screenCoords.x - mT.getMeasuredWidth() / 2, screenCoords.y - mT.getMeasuredHeight() + 5, screenCoords.x + mT.getMeasuredWidth() / 2, screenCoords.y - 20);
if(rect.contains((int)e.getX(), (int)e.getY())) {
mapView.mPoiMenuInfo.EventGeoPoint = mLocation;
mapView.mPoiMenuInfo.MarkerIndex = PoiOverlay.NO_TAP;
mapView.mPoiMenuInfo.Elevation = mElevation;
mapView.showContextMenu();
}
mLocation = null;
mapView.invalidate();
return true;
}
return super.onSingleTapUp(e, mapView);
}
@Override
public int onLongPress(MotionEvent event, TileView mapView) {
mLocation = mapView.getProjection().fromPixels((int)event.getX(), (int)event.getY(), mapView.getBearing());
mElevation = 0.0;
mSearchBubble = false;
mThreadPool.execute(new Runnable() {
@Override
public void run() {
InputStream in = null;
OutputStream out = null;
try {
in = new BufferedInputStream(new URL("http://maps.googleapis.com/maps/api/elevation/json?locations="+mLocation.toDoubleString()+"&sensor=true").openStream(), StreamUtils.IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, StreamUtils.IO_BUFFER_SIZE);
StreamUtils.copy(in, out);
out.flush();
try {
final JSONObject json = new JSONObject(dataStream.toString());
mElevation = json.getJSONArray("results").getJSONObject(0).getDouble("elevation");
} catch (JSONException e) {
mElevation = 0.0;
}
setDescr();
mMapView.postInvalidate();
} catch (Exception e) {
} catch (OutOfMemoryError e) {
System.gc();
} finally {
StreamUtils.closeStream(in);
StreamUtils.closeStream(out);
}
}
});
setDescr();
mMapView.invalidate(); //postInvalidate();
return 2;
}
private void setDescr() {
if(mLocation != null)
mDescr = new StringBuilder()
.append(LAT).append(": ")
.append(mCf.convertLat(mLocation.getLatitude()))
.append("\n").append(LON).append(": ")
.append(mCf.convertLon(mLocation.getLongitude()))
.append("\n").append(ALT).append(": ")
.append(mElevation == 0.0 ? "n/a" : mDf.formatElevation(mElevation))
.append(mCurrLocation == null ? "" : String.format(Locale.UK, "\n%s: %.1f�", AZIMUT, mCurrLocation.bearingTo360(mLocation))+"\n"+DIST+": "+mDf.formatDistance(mCurrLocation.distanceTo(mLocation)))
.toString();
}
@Override
protected void onDrawFinished(Canvas c, TileView osmv) {
}
public void fromPref(SharedPreferences settings) {
final String strlocation = settings.getString("SearchResultLocation", "");
if(strlocation.length() > 0){
mLocation = GeoPoint.fromDoubleString(strlocation);
mDescr = settings.getString("SearchResultDescr", "");
}
}
public void toPref(SharedPreferences.Editor editor){
if(mLocation != null && mSearchBubble){
editor.putString("SearchResultDescr", mDescr);
editor.putString("SearchResultLocation", mLocation.toDoubleString());
}else{
editor.putString("SearchResultDescr", "");
editor.putString("SearchResultLocation", "");
}
}
}