package org.deke.risk.riskahead;

import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RatingBar;
import android.widget.TextView;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.TileOverlay;
import com.google.android.gms.maps.model.TileOverlayOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.heatmaps.HeatmapTileProvider;
import com.google.maps.android.heatmaps.WeightedLatLng;

import org.deke.risk.riskahead.helper.IncidentReport;
import org.deke.risk.riskahead.helper.AppConfig;
import org.deke.risk.riskahead.helper.AppController;
import org.deke.risk.riskahead.helper.BaseActivity;
import org.deke.risk.riskahead.helper.OwnIconRendered;
import org.deke.risk.riskahead.helper.PlaceProvider;
import org.deke.risk.riskahead.helper.SessionManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;


public class MapsActivity extends BaseActivity implements LoaderManager.LoaderCallbacks<Cursor>,
        ClusterManager.OnClusterItemInfoWindowClickListener<IncidentReport>, ClusterManager.OnClusterClickListener<IncidentReport>, ClusterManager.OnClusterItemClickListener<IncidentReport>{

    private final static String mActivityTitle = "Risk Map";
    private static final String TAG = MapsActivity.class.getSimpleName();
    private static final Double PRELOAD_PERCENTAGE = 0.3;

    private static GoogleMap mMap;
    private Marker mMarker;
    private Marker markerShowingInfoWindow;

    private IncidentReport clickedClusterItem;
    private ClusterManager<IncidentReport> mClusterManager;

    private TileOverlay mOverlay;
    private HeatmapTileProvider mProvider;

    private LatLng myLocation;
    private LatLng markedLocation;

    private static final int DEFAULT_ZOOM_LEVEL = 14;
    private static final int THRESHOLD_ZOOM_LEVEL = 10;

    private static final int MIN_ZOOM_LEVEL = 7;

    private LatLng curNortheastBounds;
    private LatLng curSouthwestBounds;


    private boolean markersShown = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userHasToBeLoggedIn();

        findViewById(R.id.btn_maps_confirm_position).setVisibility(View.GONE);
        navDrawer.setSelection(mapAvtivityID, false);

        System.gc();

        initMap();
        handleIntent(getIntent());
        initClustering();

        findViewById(R.id.fab_reportwf_map).setVisibility(View.INVISIBLE);

    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        System.gc();
    }

    private void initMap() {
        mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.frag_maps_map)).getMap();
        mMap.getUiSettings().setZoomControlsEnabled(true);
        mMap.setMyLocationEnabled(true);

        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng point) {
                if (mMarker != null) {
                    mMarker.remove();
                }
                markedLocation = point;
                mMarker = mMap.addMarker(new MarkerOptions().position(point));
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(point, DEFAULT_ZOOM_LEVEL));
                findViewById(R.id.fab_reportwf_map).setVisibility(View.VISIBLE);

                String intentMessage = getIntent().getStringExtra(EXTRA_MESSAGE);
                if(session.getNotificationPositionRequest()){
                    findViewById(R.id.fab_reportwf_map).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            session.setLocation(Double.doubleToRawLongBits(markedLocation.latitude), Double.doubleToRawLongBits(markedLocation.longitude));
                            Log.d(TAG, "MARKED LOCATION: " + markedLocation.latitude + " " + markedLocation.longitude);
                            session.setNotificationPositionRequest(false);
                            gotoSettingsActivity();
                        }
                    });
                }else{
                    findViewById(R.id.fab_reportwf_map).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            gotoReportActivity(markedLocation.latitude + ":" + markedLocation.longitude);
                        }
                    });
                }

            }
        });
    }

    public GoogleMap.OnCameraChangeListener getCameraChangeListener() {
        return new GoogleMap.OnCameraChangeListener()
        {
            @Override
            public void onCameraChange(CameraPosition position)
            {
                mClusterManager.onCameraChange(position);

                if(position.zoom < MIN_ZOOM_LEVEL) {
                    mMap.animateCamera(CameraUpdateFactory.zoomTo(MIN_ZOOM_LEVEL));
                    return;
                }

                LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;

                Log.d("OnCameraChangeListener", "Position: "+bounds.getCenter()+" Zoom: "+position.zoom + " Bounds: NE:" + bounds.northeast + " SW: " + bounds.southwest);
                Log.d("OnCameraChangeListener", "Saved Position - Bounds: NE:" + curNortheastBounds + " SW: " + curSouthwestBounds);

                boolean isOutOfBounds = false;

                double distanceLat = Math.abs(bounds.northeast.latitude - bounds.southwest.latitude);
                double distanceLon = Math.abs(bounds.northeast.longitude - bounds.southwest.longitude);

                double southwestLat, southwestLng;
                double northeastLat, northeastLng;

                if(bounds.southwest.latitude < bounds.northeast.latitude){
                    southwestLat = bounds.southwest.latitude - distanceLat * PRELOAD_PERCENTAGE;
                    northeastLat = bounds.northeast.latitude + distanceLat * PRELOAD_PERCENTAGE;

                    if((curSouthwestBounds != null) && ((bounds.southwest.latitude < curSouthwestBounds.latitude) || (bounds.northeast.latitude > curNortheastBounds.latitude))){
                        isOutOfBounds = true;
                    }
                } else {
                    southwestLat = bounds.southwest.latitude + distanceLat * PRELOAD_PERCENTAGE;
                    northeastLat = bounds.northeast.latitude - distanceLat * PRELOAD_PERCENTAGE;

                    if((curSouthwestBounds != null) && ((bounds.southwest.latitude > curSouthwestBounds.latitude) || (bounds.northeast.latitude < curNortheastBounds.latitude))){
                        isOutOfBounds = true;
                    }
                }

                if(bounds.southwest.longitude < bounds.northeast.longitude){
                    southwestLng = bounds.southwest.longitude - distanceLon * PRELOAD_PERCENTAGE;
                    northeastLng = bounds.northeast.longitude + distanceLon * PRELOAD_PERCENTAGE;

                    if((curSouthwestBounds != null) && ((bounds.southwest.longitude < curSouthwestBounds.longitude) || (bounds.northeast.longitude > curNortheastBounds.longitude))){
                        isOutOfBounds = true;
                    }
                } else {
                    southwestLng = bounds.southwest.longitude + distanceLon * PRELOAD_PERCENTAGE;
                    northeastLng = bounds.northeast.longitude - distanceLon * PRELOAD_PERCENTAGE;

                    if((curSouthwestBounds != null) && ((bounds.southwest.longitude > curSouthwestBounds.longitude) || (bounds.northeast.longitude < curNortheastBounds.longitude))){
                        isOutOfBounds = true;
                    }
                }

                if((curSouthwestBounds == null) || isOutOfBounds) {
                    curNortheastBounds = new LatLng(northeastLat, northeastLng);
                    curSouthwestBounds = new LatLng(southwestLat, southwestLng);

                    Log.d("OnCameraChangeListener", "isOutOfBounds is true => New Calculated - Bounds: NE:" + curNortheastBounds + " SW: " + curSouthwestBounds);

                    if (position.zoom >= THRESHOLD_ZOOM_LEVEL) {
                        refreshIncidentHeatMap(curNortheastBounds, curSouthwestBounds);
                        refreshIncidentMarkers(curNortheastBounds, curSouthwestBounds);
                        markersShown = true;
                    } else if (position.zoom < THRESHOLD_ZOOM_LEVEL) {
                        mClusterManager.clearItems();
                        refreshIncidentHeatMap(curNortheastBounds, curSouthwestBounds);
                        markersShown = false;
                    }
                } else if((isOutOfBounds == false) && ((position.zoom >= THRESHOLD_ZOOM_LEVEL) && (markersShown == false))){
                    curNortheastBounds = new LatLng(northeastLat, northeastLng);
                    curSouthwestBounds = new LatLng(southwestLat, southwestLng);

                    Log.d("OnCameraChangeListener", "zoom threshold passed => New Calculated - Bounds: NE:" + curNortheastBounds + " SW: " + curSouthwestBounds);

                    refreshIncidentHeatMap(curNortheastBounds, curSouthwestBounds);
                    refreshIncidentMarkers(curNortheastBounds, curSouthwestBounds);
                    markersShown = true;
                } else if((isOutOfBounds == false) && ((position.zoom < THRESHOLD_ZOOM_LEVEL) && (markersShown == true))){
                    mClusterManager.clearItems();
                    markersShown = false;
                }
            }
        };
    }

    private void refreshIncidentMarkers(LatLng northeast, LatLng southwest){
        String tag_string_req = "getincidentsfrombound";
        StringRequest strReq = getStringRequestGetAllIncidentsFromBound(northeast,southwest);
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

    private void addIncidentMarkersOnMap(JSONArray incidents){
        mClusterManager.clearItems();

        for(int i = 0; i < incidents.length();i++){
            try {
                mClusterManager.addItem(new IncidentReport(incidents.getJSONObject(i)));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        mClusterManager.cluster();
    }

    private void refreshIncidentHeatMap(LatLng northeast, LatLng southwest){
        String tag_string_req = "getincidentsforheatmapfrombound";
        StringRequest strReq = getStringRequestGetAllIncidentsForHeatMapFromBound(northeast, southwest);
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

    private void addIncidentMarkersOnHeatMap(JSONArray incidents){
        ArrayList<WeightedLatLng> heatMapPositions = new ArrayList<>();

        for(int i = 0; i < incidents.length();i++){
            try {
                heatMapPositions.add(new WeightedLatLng(new LatLng(incidents.getJSONObject(i).getDouble("latitude"), incidents.getJSONObject(i).getDouble("longitude")),1.0));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        if(mProvider == null){
            mProvider = new HeatmapTileProvider.Builder()
                    .radius(50)
                    .weightedData(heatMapPositions)
                    .opacity(0.7)
                    .build();


            mOverlay = mMap.addTileOverlay(new TileOverlayOptions().tileProvider(mProvider));
            Log.d("HEATMAP", "HeatMap initialized");
        }else{
            mProvider.setWeightedData(heatMapPositions);
            mOverlay.clearTileCache();
            Log.d("HEATMAP", "HeatMap updated");
        }
    }

    private StringRequest getStringRequestGetAllIncidentsForHeatMapFromBound(final LatLng northeast, final LatLng southwest) {
        return new StringRequest(Request.Method.POST, AppConfig.URL_DEFAULT, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Map HeatMap positions response: " + response);

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    if (!error) {
                        JSONArray incidents = jObj.getJSONArray("msg");
                        Log.d(TAG, "HeatMap positions response length: " + incidents .length());
                        addIncidentMarkersOnHeatMap(incidents);
                    } else {
                        String errorMsg = jObj.getString("error_msg");
                        Log.e(TAG, "Error getting map heat map positions (server returned error): " + errorMsg);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error getting map positions: " + error.getMessage());
                showMessage(getString(R.string.errormsg_couldnotretrieve));
            }
        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("tag", "getincidentsforheatmapfrombound");
                params.put("uid", user.get(SessionManager.KEY_UID));
                params.put("token", user.get(SessionManager.TOKEN));
                params.put("nelat", Double.toString(northeast.latitude));
                params.put("nelng", Double.toString(northeast.longitude));
                params.put("swlat", Double.toString(southwest.latitude));
                params.put("swlng", Double.toString(southwest.longitude));

                return params;
            }
        };
    }

    private StringRequest getStringRequestGetAllIncidentsFromBound(final LatLng northeast, final LatLng southwest) {
        return new StringRequest(Request.Method.POST, AppConfig.URL_DEFAULT, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Map positions response: " + response);

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    if (!error) {
                        JSONArray incidents = jObj.getJSONArray("msg");
                        Log.d(TAG, "Map positions response length: " + incidents.length());
                        addIncidentMarkersOnMap(incidents);
                    } else {
                        String errorMsg = jObj.getString("error_msg");
                        Log.e(TAG, "Error getting map positions (server returned error): " + errorMsg);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error getting map positions: " + error.getMessage());
                showMessage(getString(R.string.errormsg_couldnotretrieve));
            }
        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("tag", "getincidentsfrombound");
                params.put("uid", user.get(SessionManager.KEY_UID));
                params.put("token", user.get(SessionManager.TOKEN));
                params.put("nelat", Double.toString(northeast.latitude));
                params.put("nelng", Double.toString(northeast.longitude));
                params.put("swlat", Double.toString(southwest.latitude));
                params.put("swlng", Double.toString(southwest.longitude));

                return params;
            }
        };
    }

    private void initClustering() {
        mClusterManager = new ClusterManager<IncidentReport>(this, mMap);
        mMap.setOnCameraChangeListener(getCameraChangeListener());

        mClusterManager.setRenderer(new OwnIconRendered(MapsActivity.this, mMap, mClusterManager));

        mMap.setOnMarkerClickListener(mClusterManager);
        mMap.setOnInfoWindowClickListener(mClusterManager);
        mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());

        mClusterManager.setOnClusterItemInfoWindowClickListener(this);

        mClusterManager.setOnClusterClickListener(this);
        mClusterManager.setOnClusterItemClickListener(this);
        mClusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<IncidentReport>() {
            @Override
            public boolean onClusterItemClick(IncidentReport item) {
                clickedClusterItem = item;
                return false;
            }
        });

        mClusterManager.getMarkerCollection().setOnInfoWindowAdapter(
                new MyCustomAdapterForItems());
    }

    private void loadInfoWindowInformation(View infoView, String incidentID){
        String tag_string_req = "getincidentscoreforinfowindow";
        StringRequest strReq = getStringRequestGetIncidentScoreForInfoWindow(infoView, incidentID);
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
    }

    private StringRequest getStringRequestGetIncidentScoreForInfoWindow(final View infoView, final String incidentID) {
        return new StringRequest(Request.Method.POST, AppConfig.URL_DEFAULT, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Map positions response: " + response);

                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    if (!error) {
                        JSONObject incident = jObj.getJSONObject("msg");
                        clickedClusterItem = new IncidentReport(incident);

                        TextView tvUsername = ((TextView) infoView.findViewById(R.id.txt_infowindow_fromuser));
                        RatingBar rbScore = ((RatingBar) infoView.findViewById(R.id.rb_infowindow_rating));

                        tvUsername.setText(getString(R.string.lbl_mapsinfowindow_author) + " " + clickedClusterItem.getFromUsername());
                        rbScore.setRating(clickedClusterItem.getScoreStars());

                        if (markerShowingInfoWindow != null && markerShowingInfoWindow.isInfoWindowShown()) {
                            markerShowingInfoWindow.showInfoWindow();
                            markerShowingInfoWindow = null;
                        }
                    } else {
                        String errorMsg = jObj.getString("error_msg");
                        Log.e(TAG, "Error getting incident details (server returned error): " + errorMsg);
                        showMessage(errorMsg);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error getting incident details: " + error.getMessage());
                showMessage(getString(R.string.errormsg_couldnotretrieve));
            }
        }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("tag", "getincidentfromincidentid");
                params.put("uid", user.get(SessionManager.KEY_UID));
                params.put("token", user.get(SessionManager.TOKEN));
                params.put("incidentid", incidentID);

                return params;
            }
        };
    }

    public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {

        private final View myContentsView;

        MyCustomAdapterForItems() {
            myContentsView = getLayoutInflater().inflate(R.layout.map_info_window, null);
        }

        @Override
        public View getInfoContents(Marker marker) {
            markerShowingInfoWindow = marker;
            return null;
        }

        @Override
        public View getInfoWindow(Marker marker) {
            markerShowingInfoWindow = marker;
            LinearLayout layCategoryColor = ((LinearLayout) myContentsView.findViewById(R.id.lay_infowindow_color));

            TextView tvCategory = ((TextView) myContentsView.findViewById(R.id.txt_infowindow_category));
            TextView tvSubcategory = ((TextView) myContentsView.findViewById(R.id.txt_infowindow_subcategory));
            TextView tvVictim = ((TextView) myContentsView.findViewById(R.id.txt_infowindow_victim));
            TextView tvSuspect = ((TextView) myContentsView.findViewById(R.id.txt_infowindow_subject));
            TextView tvTime = ((TextView) myContentsView.findViewById(R.id.txt_infowindow_time));

            if (clickedClusterItem != null) {
                loadInfoWindowInformation(myContentsView, Integer.toString(clickedClusterItem.getId()));

                layCategoryColor.setBackgroundColor(clickedClusterItem.getCategoryColor());

                tvCategory.setText(clickedClusterItem.getIncidentCategoryName(getApplicationContext()));
                tvSubcategory.setText(clickedClusterItem.getIncidentSubCategoryName(getApplicationContext()));

                tvSuspect.setText(getString(R.string.lbl_mapsinfowindow_suspect)+" "+clickedClusterItem.getSuspectString(getApplicationContext()));
                tvVictim.setText(getString(R.string.lbl_mapsinfowindow_victim)+" "+clickedClusterItem.getVictimString(getApplicationContext()));
                tvTime.setText(getString(R.string.lbl_mapsinfowindow_time)+" "+clickedClusterItem.getTimeString(getApplicationContext()));
            }
            return myContentsView;
        }
    }

    private void handleIntent(Intent intent){
        if(Intent.ACTION_SEARCH.equals(intent.getAction()))
        {
            String query = intent.getStringExtra(SearchManager.QUERY);
            doSearch(query);
        } else if(Intent.ACTION_VIEW.equals(intent.getAction())) {
            getPlace(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
        } else {
            String intentMessage = intent.getStringExtra(EXTRA_MESSAGE);

            if(intentMessage != null && intentMessage.contains(":")) {
                String[] position = intentMessage.split(":");

                String latitude = position[0];
                String longitude = position[1];

                LatLng point = new LatLng(Double.parseDouble(latitude),Double.parseDouble(longitude));
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(point, DEFAULT_ZOOM_LEVEL));
            } else {
                myPosition = session.getLocation();

                if ((myPosition != null) && (myPosition.latitude != 0.0) && (myPosition.longitude != 0.0))
                {
                    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                            new LatLng(myPosition.latitude, myPosition.longitude), DEFAULT_ZOOM_LEVEL));
                }else{
                    String sDefSystemLanguage = Locale.getDefault().getLanguage();

                    if(sDefSystemLanguage.equals("en")){
                        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                                new LatLng(51.507351, -0.127758), DEFAULT_ZOOM_LEVEL));
                    } else if (sDefSystemLanguage.equals("de")){
                        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                                new LatLng(52.518594, 13.376188), DEFAULT_ZOOM_LEVEL));
                    } else {
                        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                                new LatLng(19.410704, -99.132385), DEFAULT_ZOOM_LEVEL));
                    }
                }
            }

        }
    }

    @Override
    public boolean onClusterItemClick(IncidentReport incidentReport) {
        return false;
    }

    @Override
    public boolean onClusterClick(Cluster<IncidentReport> cluster) { return false; }

    @Override
    public void onClusterItemInfoWindowClick(IncidentReport incidentReport) {
        gotoViewReportActivity(incidentReport.getId());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        handleIntent(intent);
    }

    private void doSearch(String query){
        Bundle data = new Bundle();
        data.putString("query", query);
        getSupportLoaderManager().restartLoader(0, data, this);
    }

    private void getPlace(String query){
        Bundle data = new Bundle();
        data.putString("query", query);
        getSupportLoaderManager().restartLoader(1, data, this);
    }

    private void showLocations(Cursor c){
        MarkerOptions markerOptions;
        LatLng position = null;
        //mMap.clear();

        while(c.moveToNext()){
            markerOptions = new MarkerOptions();
            position = new LatLng(Double.parseDouble(c.getString(1)),Double.parseDouble(c.getString(2)));
            markerOptions.position(position);
            markerOptions.title(c.getString(0));
        }
        if(position!=null){
            CameraUpdate cameraPosition = CameraUpdateFactory.newLatLng(position);
            mMap.animateCamera(cameraPosition);
        }

        if (position != null) {
            myLocation = new LatLng(position.latitude,position.longitude);
        }
        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myLocation, DEFAULT_ZOOM_LEVEL));
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {}

    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle query) {
        CursorLoader cLoader = null;
        if(arg0==0)
            cLoader = new CursorLoader(getBaseContext(), PlaceProvider.SEARCH_URI, null, null, new String[]{query.getString("query") }, null);
        else if(arg0==1)
            cLoader = new CursorLoader(getBaseContext(), PlaceProvider.DETAILS_URI, null, null, new String[]{ query.getString("query") }, null);
        return cLoader;

    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor c) {
        showLocations(c);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_maps, menu);
        getMenuInflater().inflate(R.menu.menu_common, menu);

        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.location_search).getActionView();
        SearchableInfo searchInfo = searchManager.getSearchableInfo(getComponentName());
        searchView.setSearchableInfo(searchInfo);

        EditText txtSearch = ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text));
        txtSearch.setHint(getResources().getString(R.string.search_hint));
        txtSearch.setHintTextColor(Color.LTGRAY);
        txtSearch.setTextColor(Color.WHITE);

        return true;
    }

    @Override
    protected void onPause(){
        super.onPause();
        showAd();
    }

    @Override
    public void onDestroy() {
        if (mMap != null) {
            getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.frag_maps_map)).commitAllowingStateLoss();
            mMap = null;
        }
        session.setNotificationPositionRequest(false);
        super.onDestroy();
    }

    @Override
    protected int getLayoutResourceId() {
        return R.layout.activity_maps;
    }

    @Override
    protected String getActivityName() {
        return mActivityTitle;
    }

    public void onBackPressed(){
        session.setNotificationPositionRequest(false);
        super.onBackPressed();

    }
}
