/*
 * Copyright 2015 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.samples.apps.iosched.map.util;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.content.AsyncTaskLoader;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.geojson.GeoJsonFeature;
import com.google.maps.android.geojson.GeoJsonLayer;
import com.google.maps.android.geojson.GeoJsonPoint;
import com.google.maps.android.geojson.GeoJsonPointStyle;
import com.google.maps.android.ui.IconGenerator;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import com.google.samples.apps.iosched.util.MapUtils;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Background task that queries the content provider and prepares a {@link GeoJsonLayer} that can be
 * used to create Markers.
 */
public class MarkerLoadingTask extends AsyncTaskLoader<GeoJsonLayer> {

    private GoogleMap mMap;
    private Context mContext;

    public MarkerLoadingTask(GoogleMap map, Context context) {
        super(context);
        mContext = context;
        mMap = map;
    }

    @Override
    public GeoJsonLayer loadInBackground() {
        try {
            final Uri uri = ScheduleContract.MapGeoJson.buildGeoJsonUri();
            Cursor cursor = getContext().getContentResolver().query(uri, MarkerQuery.PROJECTION,
                    null, null, null);

            GeoJsonLayer layer = null;
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    final String id = cursor.getString(MarkerQuery.GEOJSON);
                    JSONObject j = new JSONObject(id);
                    //GeoJsonLayer stores a map, which is only modified when addLayerToMap is called
                    layer = new GeoJsonLayer(mMap, j);
                } else {
                    return null;
                }
                cursor.close();
            }
            Iterable<GeoJsonFeature> features = layer.getFeatures();
            final IconGenerator labelIconGenerator = MapUtils.getLabelIconGenerator(getContext());
            for (GeoJsonFeature feature : features) {
                // get data
                final String id = feature.getProperty("id");
                GeoJsonPoint point = (GeoJsonPoint) feature.getGeometry();
                final LatLng position = point.getCoordinates();
                final String typeString = feature.getProperty("type");
                final int type = MapUtils.detectMarkerType(typeString);
                final String label = feature.getProperty("title");

                GeoJsonPointStyle pointStyle = new GeoJsonPointStyle();
                if (type == MarkerModel.TYPE_LABEL) {
                    // Label markers contain the label as its icon
                    pointStyle = MapUtils.createLabelMarker(labelIconGenerator, id, label);
                } else if (type == MarkerModel.TYPE_ICON) {
                    // An icon marker is mapped to a drawable based on its full type name
                    pointStyle = MapUtils.createIconMarker(typeString, id, getContext());
                } else if (type != MarkerModel.TYPE_INACTIVE) {
                    // All other markers (that are not inactive) contain a pin icon
                    pointStyle = MapUtils.createPinMarker(id);
                }
                pointStyle.setVisible(true);
                feature.setPointStyle(pointStyle);
            }
            return layer;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    private interface MarkerQuery {
        String[] PROJECTION = {
                ScheduleContract.MapGeoJson.GEOJSON
        };

        int GEOJSON = 0;
    }

}

@@ -1346,16 +1346,44 @@
 bject;%0A%0A
+import java.util.Iterator;%0A%0A
 /**%0A * B
@@ -2587,32 +2587,33 @@
 ;%0A            %7D%0A
+%0A
             Iter
@@ -2613,19 +2613,19 @@
    Itera
-ble
+tor
 %3CGeoJson
@@ -2633,24 +2633,24 @@
 eature%3E 
-features
+iterator
  = layer
@@ -2659,24 +2659,35 @@
 etFeatures()
+.iterator()
 ;%0A          
@@ -2791,13 +2791,53 @@
     
-for (
+while (iterator.hasNext()) %7B%0A                
 GeoJ
@@ -2859,21 +2859,27 @@
 ure 
-: features) %7B
+= iterator.next();%0A
 %0A   
@@ -4060,32 +4060,243 @@
               %7D%0A
+%0A                // If the marker is invalid (e.g. the icon does not exist), remove it from the map.%0A                if (pointStyle == null) %7B%0A                    iterator.remove();%0A                %7D else %7B%0A    
                 
@@ -4320,24 +4320,28 @@
 ible(true);%0A
+    
             
@@ -4375,24 +4375,42 @@
 ointStyle);%0A
+                %7D%0A
             

Fix NPE when marker icon does not exist.