Newer
Older
mountainnavigation / app / src / main / java / de / apps4ics / mountainnavigation / handlers / PoiHandler.java
/**
 * This file is part of MountainNavigation.
 *
 * MountainNavigation 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.
 *
 * MountainNavigation 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 MountainNavigation.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @copyright Copyright (c) 2016 Vinzenz Rosenkanz <vinzenz.rosenkranz@gmail.com>
 *
 * @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
 */

package de.apps4ics.mountainnavigation.handlers;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Location;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;

import org.osmdroid.api.IMapController;
import org.osmdroid.bonuspack.location.POI;
import org.osmdroid.bonuspack.overlays.MapEventsOverlay;
import org.osmdroid.bonuspack.overlays.MapEventsReceiver;
import org.osmdroid.bonuspack.overlays.Marker;
import org.osmdroid.bonuspack.overlays.Polyline;
import org.osmdroid.bonuspack.routing.OSRMRoadManager;
import org.osmdroid.bonuspack.routing.Road;
import org.osmdroid.bonuspack.routing.RoadManager;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.OverlayItem;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import de.apps4ics.mountainnavigation.MainActivity;
import de.apps4ics.mountainnavigation.R;
import de.apps4ics.mountainnavigation.overlays.ImageDialogItemizedIconOverlay;
import de.apps4ics.mountainnavigation.overlays.MapDialogItemizedIconOverlay;
import de.apps4ics.mountainnavigation.pois.AddBreakpointDialog;
import de.apps4ics.mountainnavigation.pois.AddFountainDialog;
import de.apps4ics.mountainnavigation.pois.AddHutDialog;
import de.apps4ics.mountainnavigation.pois.AddPathDialog;
import de.apps4ics.mountainnavigation.pois.AddPeakDialog;
import de.apps4ics.mountainnavigation.pois.AddPoiDialog;
import de.apps4ics.mountainnavigation.pois.CellReception;
import de.apps4ics.mountainnavigation.pois.DbGeoPoint;
import de.apps4ics.mountainnavigation.pois.Fountain;
import de.apps4ics.mountainnavigation.pois.Image;
import de.apps4ics.mountainnavigation.pois.Lift;
import de.apps4ics.mountainnavigation.pois.Options;
import de.apps4ics.mountainnavigation.pois.Path;
import de.apps4ics.mountainnavigation.pois.Poi;
import de.apps4ics.mountainnavigation.pois.Types;
import de.apps4ics.mountainnavigation.pois.Wifi;

public class PoiHandler {
    private static List<Marker>[] poiMarkers;
    private static RoadManager roadManager;
    private Map<String, List<POI>> pois;
    private Resources res;
    private MapView mapView;
    private DatabaseHandler dbHandler;
    private OsmHandler osmHandler;
    private Context context;
    private Activity activity;
    private FragmentManager fragmentManager;
    private Vibrator v;

    private static final long VIB_LENGTH = 50;
    public final static int SELECT_POI_PHOTO = 1;

    private static String[] fountainSizes;
    private static String[] pathOptions;
    private static String[] pathDescs;
    private static Integer[] pathOptionImgs;
    private static String[] hutTypes;
    private static String[] breakPointOptions;
    private static Integer[] breakPointOptionsImgs;
    private static Integer[] fountainImgs;
    private static String[] entries;
    private static Integer[] entryImgs;

    public PoiHandler(Context context, Resources res, MapView mapView) {
        poiMarkers = new ArrayList[Types.SIZE];
        for(int i=0; i<poiMarkers.length; ++i){
            poiMarkers[i] = new ArrayList<>();
        }
        dbHandler = new DatabaseHandler(context);
        osmHandler = new OsmHandler();
        this.context = context;
        this.res = res;
        this.mapView = mapView;

        roadManager = new OSRMRoadManager(getContext());

        v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);

        try {
            activity = (Activity) context;
            fragmentManager = activity.getFragmentManager();
        } catch(ClassCastException e) {
            Log.e(MainActivity.TAG, "Could not get fragment manager!");
        }

        fountainSizes = res.getStringArray(R.array.fountain_size_dialog_options);
        fountainImgs = new Integer[]{
                R.drawable.fountain_size_small,
                R.drawable.fountain_size_medium,
                R.drawable.fountain_size_big,
        };
        pathDescs = res.getStringArray(R.array.path_dialog_descs);
        pathOptions = res.getStringArray(R.array.path_dialog_options);
        pathOptionImgs = new Integer[]{
                R.mipmap.path_exposed,
                R.mipmap.path_difficult_wet,
                R.mipmap.path_giddiness,
                R.mipmap.path_climbing
        };
        hutTypes = res.getStringArray(R.array.hut_dialog_types);
        breakPointOptions = res.getStringArray(R.array.break_point_dialog_options);
        breakPointOptionsImgs = new Integer[]{
                R.mipmap.ic_rock,
                R.mipmap.ic_bench,
                R.mipmap.ic_table,
                R.mipmap.ic_roofed
        };

        entries = res.getStringArray(R.array.toggleEntries);
        entryImgs  = new Integer[]{
                R.mipmap.water,
                R.drawable.path,
                R.mipmap.ic_cabin,
                R.mipmap.ic_peak,
                R.drawable.break_point,
                R.drawable.trash,
                R.drawable.image_upload,
                R.drawable.cell_reception,
                R.drawable.wifi,
                R.mipmap.cable_car
        };
    }

    public Context getContext() {
        return context;
    }

    public Activity getActivity() { return activity; }

    public static String[] getFountainSizes() {
        return fountainSizes;
    }

    public static String[] getPathOptions() {
        return pathOptions;
    }

    public static String[] getPathDescs() {
        return pathDescs;
    }

    public static Integer[] getPathOptionImgs() {
        return pathOptionImgs;
    }

    public static String[] getHutTypes() {
        return hutTypes;
    }

    public static String[] getBreakPointOptions() {
        return breakPointOptions;
    }

    public static Integer[] getBreakPointOptionsImgs() {
        return breakPointOptionsImgs;
    }

    public static Integer[] getFountainImgs() {
        return fountainImgs;
    }

    public static Integer[] getEntryImgs() {
        return entryImgs;
    }

    public static String[] getEntries() {
        return entries;
    }

    public static RoadManager getRoadManager() { return roadManager; }

    public static void addPoiMarker(int type, Marker marker) {
        poiMarkers[type].add(marker);
    }

    public List<Poi> getPoisAround(double lat, double lon) {
        return getPoisAround(lat, lon, -1);
    }

    public List<Poi> getPoisAround(double lat, double lon, int limit) {
        if(MainActivity.hasInternet()) return getPoisAroundOnline(lat, lon, limit);
        else return getPoisAroundCached(lat, lon, limit);
    }

    private List<Poi> getPoisAroundOnline(double lat, double lon, int limit) {
        ArrayList<POI> pois = new ArrayList<>(osmHandler.getPoisAround(lat, lon, limit));
        ArrayList<Poi> convertedPois = new ArrayList<>();
        for(POI p : pois) {
            convertedPois.add(new Poi(p));
        }
        return convertedPois;
    }

    private List<Poi> getPoisAroundCached(double lat, double lon, int limit) {
        return dbHandler.getPoisAround(lat, lon, limit);
    }

    public void getPoisAlong(double lat, double lon) {
        getPoisAlong(lat, lon, -1);
    }

    public void getPoisAlong(double lat, double lon, int limit) {

    }

    private void getPoisAlongOnline(double lat, double lon, int limit) {

    }

    private void getPoisAlongCached(double lat, double lon, int limit) {

    }

    private void addPoiToOsm(double lat, double lon, double alt, int type, Options options) {

    }

    public void updatePoi(Poi poi) {
        updatePoiInCache(poi);
        if(MainActivity.hasInternet()) updatePoiInOsm(poi);
        else ; //TODO callback for upload, not part of core
    }

    private void updatePoiInOsm(Poi poi) {
        //TODO OSM stuff, not part of core
    }

    private void updatePoiInCache(Poi poi) {
        dbHandler.updatePoi(poi);
    }

    public List<Marker> getPoiIcons(int type, String title) {
        UpdatePoiIconsAsyncTask task = new UpdatePoiIconsAsyncTask(type, title, res, mapView);
        List<Poi> tempPoiList = dbHandler.getPoiByType(type);
        try {
            poiMarkers[type] = task.execute(tempPoiList).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return poiMarkers[type];
    }

    public void disablePois(int type) {
        for(int i=0; i<poiMarkers[type].size(); ++i){
            Overlay poi = poiMarkers[type].get(i);
            mapView.getOverlays().remove(poi);
        }
        poiMarkers[type] = new ArrayList<>();
    }

    public AddPoiDialog createAddPoiDialog() {
        return new AddPoiDialog();
    }

    public void addFountain(){
        AddFountainDialog addFountainDialog = new AddFountainDialog();
        addFountainDialog.show(fragmentManager, "Add fountain POI Dialog");
    }

    public void addBreakpoint(){
        AddBreakpointDialog addBreakpointDialog = new AddBreakpointDialog();
        addBreakpointDialog.show(fragmentManager, "Add Break point POI Dialog");
    }

    public void addHut(){
        AddHutDialog addHutDialog = new AddHutDialog();
        addHutDialog.show(fragmentManager, "Add Hut POI Dialog");
    }

    public void addPeak(){
        AddPeakDialog addPeakDialog = new AddPeakDialog();
        addPeakDialog.show(fragmentManager, "Add Peak POI Dialog");
    }

    public void addPathMap() {
        final MapView popupMapView = new MapView(context);
        popupMapView.setTileSource(TileSourceFactory.MAPNIK);
        popupMapView.setBuiltInZoomControls(false);
        popupMapView.setMultiTouchControls(true);
        IMapController popupMapController = popupMapView.getController();
        popupMapController.setZoom(MainActivity.ZOOM_LEVEL);
        Location mLocation = MainActivity.getLocation();
        popupMapController.setCenter(new GeoPoint(mLocation.getLatitude(), mLocation.getLongitude()));

        List<OverlayItem> overlayItemList = new ArrayList<>();
        for(Location l : MainActivity.getFoundLocations()){
            OverlayItem oI = new OverlayItem(String.valueOf(l.getTime()), null, null, new GeoPoint(l.getLatitude(), l.getLongitude(), l.getAltitude()));
            oI.setMarker(res.getDrawable(R.mipmap.ic_poi_red, null));
            overlayItemList.add(oI);
        }

        List<Poi> poiMarker = dbHandler.getAllPois();
        for(Poi p : poiMarker){
            DbGeoPoint dbgp = dbHandler.getGeoPointsForPoi(p.getId(), p.getType()).get(0);
            GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
            OverlayItem oI = new OverlayItem(String.valueOf(dbgp.getTime()), String.valueOf(p.getId()), String.valueOf(p.getType()), gp);
            Drawable[] iconLayer = new Drawable[2];
            iconLayer[0] = res.getDrawable(R.mipmap.ic_poi, null);
            BitmapDrawable bd = (BitmapDrawable) res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(p.getType())], null);
            if(bd == null) continue;
            Bitmap b = bd.getBitmap();
            Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
            bd = new BitmapDrawable(res, bResized);
            bd.setGravity(Gravity.CENTER_HORIZONTAL);
            iconLayer[1] = bd;
            LayerDrawable icon = new LayerDrawable(iconLayer);
            oI.setMarker(icon);
            overlayItemList.add(oI);
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setView(popupMapView)
                .setTitle(R.string.path_map_dialog_title)
                .setPositiveButton(R.string.continue_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        AddPathDialog addPathDialog = new AddPathDialog();
                        addPathDialog.show(fragmentManager, "Add Path POI Dialog");
                    }
                })
                .setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        AlertDialog pathMapDialog = builder.create();
        pathMapDialog.show();
        pathMapDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        final MapDialogItemizedIconOverlay overlay = new MapDialogItemizedIconOverlay(context, overlayItemList, pathMapDialog, popupMapView);

        MapEventsReceiver eventsReceiver = new MapEventsReceiver() {
            @Override
            public boolean singleTapConfirmedHelper(GeoPoint geoPoint) {
                return false;
            }

            @Override
            public boolean longPressHelper(GeoPoint geoPoint) {
                v.vibrate(VIB_LENGTH);
                OverlayItem oI = new OverlayItem("", null, null, geoPoint);
                oI.setMarker(context.getResources().getDrawable(R.mipmap.ic_poi_red, null));
                overlay.addItem(oI);
                popupMapView.invalidate();
                return true;
            }
        };

        popupMapView.getOverlays().add(new MapEventsOverlay(context, eventsReceiver));
        popupMapView.getOverlays().add(overlay);
    }

    public void addLiftMap() {
        final MapView popupMapView = new MapView(context);
        popupMapView.setTileSource(TileSourceFactory.MAPNIK);
        popupMapView.setBuiltInZoomControls(false);
        popupMapView.setMultiTouchControls(true);
        IMapController popupMapController = popupMapView.getController();
        popupMapController.setZoom(MainActivity.ZOOM_LEVEL);
        Location mLocation = MainActivity.getLocation();
        popupMapController.setCenter(new GeoPoint(mLocation.getLatitude(), mLocation.getLongitude()));

        List<OverlayItem> overlayItemList = new ArrayList<>();
        for(Location l : MainActivity.getFoundLocations()){
            OverlayItem oI = new OverlayItem(String.valueOf(l.getTime()), null, null, new GeoPoint(l.getLatitude(), l.getLongitude(), l.getAltitude()));
            oI.setMarker(res.getDrawable(R.mipmap.ic_poi_red, null));
            overlayItemList.add(oI);
        }

        List<Poi> poiMarker = dbHandler.getAllPois();
        for(Poi p : poiMarker){
            DbGeoPoint dbgp = dbHandler.getGeoPointsForPoi(p.getId(), p.getType()).get(0);
            GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
            OverlayItem oI = new OverlayItem(String.valueOf(dbgp.getTime()), String.valueOf(p.getId()), String.valueOf(p.getType()), gp);
            Drawable[] iconLayer = new Drawable[2];
            iconLayer[0] = res.getDrawable(R.mipmap.ic_poi, null);
            BitmapDrawable bd = (BitmapDrawable) res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(p.getType())], null);
            if(bd == null) continue;
            Bitmap b = bd.getBitmap();
            Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
            bd = new BitmapDrawable(res, bResized);
            bd.setGravity(Gravity.CENTER_HORIZONTAL);
            iconLayer[1] = bd;
            LayerDrawable icon = new LayerDrawable(iconLayer);
            oI.setMarker(icon);
            overlayItemList.add(oI);
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setView(popupMapView)
                .setTitle(R.string.lift_map_dialog_title)
                .setPositiveButton(R.string.continue_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ArrayList<OverlayItem> pathMarkers = MainActivity.getPathMarkers();
                        ArrayList<GeoPoint> waypoints = new ArrayList<>();
                        long poiId = addPoi(new Lift(0, ""));
                        for(int i=0; i<pathMarkers.size(); ++i){
                            GeoPoint gp = (GeoPoint) pathMarkers.get(i).getPoint();
                            waypoints.add(gp);
                            long time = 0;
                            long rowId = 0;
                            String uid = pathMarkers.get(i).getUid();
                            if(uid != null && !uid.equals("")){
                                String timeStr = pathMarkers.get(i).getUid();
                                String idStr = pathMarkers.get(i).getTitle();
                                if(timeStr != null && !timeStr.equals("")) time = Long.parseLong(timeStr) / 1000;
                                if(idStr != null && !idStr.equals("")) rowId = Long.parseLong(idStr);
                            }

                            addGp(new DbGeoPoint(gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), time, poiId, Types.LIFT));
                        }
                        try {
                            Road road = new GetRoadFromOsm().execute(waypoints.toArray(new GeoPoint[waypoints.size()])).get();
                            Polyline line = RoadManager.buildRoadOverlay(road, getContext());
                            MainActivity.getMapView().getOverlays().add(line);
                            MainActivity.getMapView().invalidate();
                        } catch (InterruptedException e) {
                        } catch (ExecutionException e) {
                        }
                        MainActivity.setPathMarkers(new ArrayList<OverlayItem>());
                    }
                })
                .setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        AlertDialog pathMapDialog = builder.create();
        pathMapDialog.show();
        pathMapDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        final MapDialogItemizedIconOverlay overlay = new MapDialogItemizedIconOverlay(context, overlayItemList, pathMapDialog, popupMapView);

        MapEventsReceiver eventsReceiver = new MapEventsReceiver() {
            @Override
            public boolean singleTapConfirmedHelper(GeoPoint geoPoint) {
                return false;
            }

            @Override
            public boolean longPressHelper(GeoPoint geoPoint) {
                Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
                v.vibrate(VIB_LENGTH);
                OverlayItem oI = new OverlayItem("", null, null, geoPoint);
                oI.setMarker(context.getResources().getDrawable(R.mipmap.ic_poi_red, null));
                overlay.addItem(oI);
                popupMapView.invalidate();
                return true;
            }
        };

        popupMapView.getOverlays().add(new MapEventsOverlay(context, eventsReceiver));
        popupMapView.getOverlays().add(overlay);
    }

    public void addImageMap() {
        final MapView popupMapView = new MapView(context);
        popupMapView.setTileSource(TileSourceFactory.MAPNIK);
        popupMapView.setBuiltInZoomControls(false);
        popupMapView.setMultiTouchControls(true);
        IMapController popupMapController = popupMapView.getController();
        popupMapController.setZoom(MainActivity.ZOOM_LEVEL);
        Location mLocation = MainActivity.getLocation();
        popupMapController.setCenter(new GeoPoint(mLocation.getLatitude(), mLocation.getLongitude()));

        List<OverlayItem> overlayItemList = new ArrayList<>();
        List<Poi> poiMarker = dbHandler.getAllPois();
        for(Poi p : poiMarker){
            DbGeoPoint dbgp = dbHandler.getGeoPointsForPoi(p.getId(), p.getType()).get(0);
            GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
            OverlayItem oI = new OverlayItem(String.valueOf(dbgp.getTime()), String.valueOf(p.getId()), String.valueOf(p.getType()), gp);
            Drawable[] iconLayer = new Drawable[2];
            iconLayer[0] = res.getDrawable(R.mipmap.ic_poi, null);
            BitmapDrawable bd = (BitmapDrawable) res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(p.getType())], null);
            if(bd == null) continue;
            Bitmap b = bd.getBitmap();
            Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
            bd = new BitmapDrawable(res, bResized);
            bd.setGravity(Gravity.CENTER_HORIZONTAL);
            iconLayer[1] = bd;
            LayerDrawable icon = new LayerDrawable(iconLayer);
            oI.setMarker(icon);
            overlayItemList.add(oI);
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setView(popupMapView)
                .setTitle(R.string.image_map_dialog_title)
                .setPositiveButton(R.string.continue_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        activity.startActivityForResult(galleryIntent, SELECT_POI_PHOTO);
                    }
                })
                .setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        AlertDialog pathMapDialog = builder.create();
        pathMapDialog.show();
        pathMapDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
        final ImageDialogItemizedIconOverlay overlay = new ImageDialogItemizedIconOverlay(context, overlayItemList, pathMapDialog, popupMapView);
        popupMapView.getOverlays().add(overlay);
    }

    public void addCellReceptionPoi(){
        if(MainActivity.hasInternet()){
            TelephonyManager tm = MainActivity.getTelephonyManager();
            int networkStrength = MainActivity.getNetworkStrength();
            if(tm != null && networkStrength != -1){
                String opName = tm.getNetworkOperatorName();
                String opCountry = tm.getNetworkCountryIso();
                String nwType = MainActivity.getActiveNetwork().getSubtypeName();
                int roaming = (tm.isNetworkRoaming()) ? 1 : 0;
                addPoi(new CellReception(0, networkStrength, opName, opCountry, roaming, nwType));
            } else {
                Log.d(MainActivity.TAG, "You are not connected to a phone network");
            }
        } else {
            Log.d(MainActivity.TAG, "You are not connected to any network");
        }
    }

    public void addWifiPoi(){
        if(!MainActivity.getWifiManager().isWifiEnabled()){
            AlertDialog.Builder wifiIntentDialogBuilder = new AlertDialog.Builder(context);
            wifiIntentDialogBuilder
                    .setTitle(R.string.wifi_disabled_title)
                    .setMessage(R.string.wifi_disabled_text)
                    .setPositiveButton(R.string.enable_wifi_button, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                            context.startActivity(intent);
                        }
                    })
                    .setNegativeButton(R.string.dont_enable_wifi_button, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    });
            AlertDialog wifiIntentDialog = wifiIntentDialogBuilder.create();
            wifiIntentDialog.show();
        } else {
            if(MainActivity.hasInternet()){
                if (MainActivity.getActiveNetwork().getType() == ConnectivityManager.TYPE_WIFI) {
                    WifiManager wm = MainActivity.getWifiManager();
                    String ssid = wm.getConnectionInfo().getSSID();
                    int rssi = wm.getConnectionInfo().getRssi();
                    int levels = WifiManager.calculateSignalLevel(rssi, MainActivity.MAX_WIFI_LEVELS);
                    Log.d(MainActivity.TAG, "You are currently connected to '" + ssid + "' with " + levels + " (" + rssi + ")");
                    addPoi(new Wifi(0, ssid, levels));
                } else {
                    Log.d(MainActivity.TAG, "Wifi network not available/connected");
                }
            } else {
                Log.d(MainActivity.TAG, "You are not connected to any network");
            }
        }
    }

    public void addImagePoi(Uri data){
        byte[] imgData = createImage(data);
        if(imgData == null || MainActivity.imageMarker == null) Log.d(MainActivity.TAG, "image data or marker is null...");
        String file = getFilePath(data);

        int type = Integer.parseInt(MainActivity.imageMarker.getSnippet()); //Long.parseLong(uidParts[1]);
        long id = Long.parseLong(MainActivity.imageMarker.getTitle());
        long imgId = dbHandler.addPoi(new Image(0, imgData, id, type));
        DbGeoPoint dbgp;
        ExifInterface exifInterface = null;
        try {
            exifInterface = new ExifInterface(file);
        } catch(IOException e){
            Log.e(MainActivity.TAG, "File " + file + " not found!");
        }
        float[] exifLatLon = new float[2];
        if(exifInterface != null && exifInterface.getLatLong(exifLatLon)){
            double alt = exifInterface.getAltitude(0);

            SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy:M:d H:m:s", Locale.getDefault());
            String timestamp = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
            long time = 0;
            if(timestamp != null){
                try {
                    time = timestampFormat.parse(timestamp).getTime() / 1000;
                } catch(ParseException pe) {
                    pe.printStackTrace();
                }
            }

            dbgp = new DbGeoPoint(exifLatLon[0], exifLatLon[1], alt, time, imgId, Types.PIC);
        } else {
            dbgp = dbHandler.getGeoPointsForPoi(id, type).get(0);
            dbgp.set_poiId(imgId);
            dbgp.set_poiType(Types.PIC);
        }
        dbHandler.addPoi(dbgp);
    }

    public long addGp(DbGeoPoint dbgp){
        return dbHandler.addPoi(dbgp);
    }

    public long addPoi(Poi poi){
        long rowId = dbHandler.addPoi(poi);
        if(rowId >= 0) MainActivity.Toaster(context.getString(R.string.add_poi_success), true, context);
        if(poi.getType() == Types.GP || poi.getType() == Types.HIKE) return rowId;
        Location mLocation = MainActivity.getLocation();
        double _lat = mLocation.getLatitude();
        double _lon = mLocation.getLongitude();
        double _alt = mLocation.getAltitude();
        long _time = System.currentTimeMillis() / 1000;

        DbGeoPoint dbgp = new DbGeoPoint(_lat, _lon, _alt, _time, rowId, poi.getType());
        long gp_id = dbHandler.addPoi(dbgp);
        if(MainActivity.hasInternet()) addPoiToOsm(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt(), poi.getType(), null);
        else ;//TODO add callback, not part of core
        return rowId;
    }

    private byte[] createImage(Uri uri) {
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(uri);
            ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];

            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                byteBuffer.write(buffer, 0, len);
            }
            return byteBuffer.toByteArray();
        } catch (FileNotFoundException e) {
            Log.e(MainActivity.TAG, "The file at Uri " + uri.toString() + " does not exist!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getFilePath(Uri uri){
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(uri, filePathColumn, null, null, null);
        String filePath = null;
        if(cursor != null && cursor.moveToFirst()){
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            filePath = cursor.getString(columnIndex);
            cursor.close();
        }
        return filePath;
    }

    public static LayerDrawable createPoiMarker(int type) {
        Resources res = MainActivity.getRes();
        Drawable[] iconLayer = new Drawable[2];
        iconLayer[0] = res.getDrawable(R.mipmap.ic_poi, null);
        BitmapDrawable bd = (BitmapDrawable) res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(type)], null);
        if(bd == null) return null;
        Bitmap b = bd.getBitmap();
        Bitmap bResized = Bitmap.createScaledBitmap(b, b.getWidth()/2, b.getHeight()/2, false);
        bd = new BitmapDrawable(res, bResized);
        bd.setGravity(Gravity.CENTER_HORIZONTAL);
        iconLayer[1] = bd;
        return new LayerDrawable(iconLayer);
    }
}

class UpdatePoiIconsAsyncTask extends AsyncTask<List<Poi>, Void, List<Marker>> {
    private int type;
    private String title;
    private Resources res;
    private MapView mapView;

    public UpdatePoiIconsAsyncTask(int type, String title, Resources res, MapView mapView){
        this.type = type;
        this.title = title;
        this.res = res;
        this.mapView = mapView;
    }

    @Override
    protected List<Marker> doInBackground(List<Poi>... params) {
        //TODO get weather and rate POIs (if sunny, smaller fountains, ...), not part of core
        List<Marker> result = new ArrayList<>();
        List<Poi> tempPoiList = params[0]; //This is only one list
        for(int i=0; i<tempPoiList.size(); ++i){
            Poi poi = tempPoiList.get(i);
            ArrayList<DbGeoPoint> dbgps = (ArrayList<DbGeoPoint>) MainActivity.getDbHandler().getGeoPointsForPoi(poi.getId(), poi.getType());
            DbGeoPoint dbgp = dbgps.get(0);
            GeoPoint gp = new GeoPoint(dbgp.getLat(), dbgp.getLon(), dbgp.getAlt());
            String titleText = title;
            String snippetText = res.getString(R.string.osm_marker_snippet, gp.getLatitude(), gp.getLongitude(), gp.getAltitude(), MainActivity.df_full.format(new Date(dbgp.getTime())));

            switch(type){
                case Types.FOUNTAIN:
                    titleText += " (" + PoiHandler.getFountainSizes()[((Fountain) poi).getSize()] + ")";
                    break;
                case Types.PATH: {
                    Path p = (Path) poi;
                    DbGeoPoint pathEnd = dbgps.get(1);
                    titleText += " (" + p.getLength() + ")";
                    snippetText += "\n";
                    snippetText += "Exposed: " + ((p.getExposed() == 1) ? "Yes!" : "No!");
                    snippetText += "\n";
                    snippetText += "Difficult: " + ((p.getDiffWet() == 1) ? "Yes!" : "No!");
                    snippetText += "\n";
                    snippetText += "Giddiness: " + ((p.getGiddiness() == 1) ? "Yes!" : "No!");
                    snippetText += "\n";
                    snippetText += "Climbing: " + ((p.getClimbing() == 1) ? "Yes!" : "No!");
                    Marker positionMarker = new Marker(mapView);
                    positionMarker.setPosition(new GeoPoint(pathEnd.getLat(), pathEnd.getLon(), pathEnd.getAlt()));
                    positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
                    positionMarker.setTitle(titleText);
                    positionMarker.setSnippet(snippetText);
                    positionMarker.setImage(res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(type)], null));
                    positionMarker.setIcon(PoiHandler.createPoiMarker(type));
                    result.add(positionMarker);
                    PoiHandler.addPoiMarker(MainActivity.getPos(type), positionMarker);
                }
                break;
            }

            Marker positionMarker = new Marker(mapView);
            positionMarker.setPosition(gp);
            positionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
            positionMarker.setTitle(titleText);
            positionMarker.setSnippet(snippetText);
            positionMarker.setImage(res.getDrawable(PoiHandler.getEntryImgs()[MainActivity.getPos(type)], null));
            positionMarker.setIcon(PoiHandler.createPoiMarker(type));
            result.add(positionMarker);
            PoiHandler.addPoiMarker(MainActivity.getPos(type), positionMarker);
        }
        return result;
    }
}