/*
 *  Copyright (C) 2014-2015 Stichting Akvo (Akvo Foundation)
 *
 *  This file is part of Akvo FLOW.
 *
 *  Akvo FLOW is free software: you can redistribute it and modify it under the terms of
 *  the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
 *  either version 3 of the License or any later version.
 *
 *  Akvo FLOW 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 Affero General Public License included below for more details.
 *
 *  The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
 */

package org.akvo.gae.remoteapi;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;

public class DeleteData implements Process {

    @Override
    public void execute(DatastoreService ds, String[] args) throws Exception {

        final Long surveyId = Long.parseLong(args[0]);

        final List<String> kinds = Arrays.asList("SurveyalValue", "QuestionAnswerStore",
                "SurveyInstance");

        for (String kind : kinds) {
            deleteEntities(ds, kind, surveyId);
        }

        deleteSurveyedLocale(ds, surveyId);
    }

    private static void deleteEntities(DatastoreService ds, String kind, Long surveyId) {
        final Filter f = new FilterPredicate("surveyId", FilterOperator.EQUAL, surveyId);
        final Query q = new Query(kind).setFilter(f).setKeysOnly();
        final PreparedQuery pq = ds.prepare(q);
        final List<Key> keys = new ArrayList<Key>();
        for (Entity e : pq.asList(FetchOptions.Builder.withChunkSize(500))) {
            keys.add(e.getKey());
        }
        System.out.println(String.format("%s - deleting %s enties - surveyId = %s", kind,
                keys.size(), surveyId));
        ds.delete(keys);
    }

    @SuppressWarnings("unchecked")
    private static void deleteSurveyedLocale(DatastoreService ds, Long surveyId) {
        // NOTE: It's not possible to query by the `surveyInstanceContrib` property
        final Query q = new Query("SurveyedLocale");
        final PreparedQuery pq = ds.prepare(q);
        final List<Key> keys = new ArrayList<Key>();

        for (Entity e : pq.asList(FetchOptions.Builder.withChunkSize(500))) {
            Collection<Long> contrib = (Collection<Long>) e.getProperty("surveyInstanceContrib");
            if (contrib != null && contrib.size() == 1 && contrib.contains(surveyId)) {
                keys.add(e.getKey());
            }
        }
        System.out.println(String.format("SurveyedLocale - deleting %s enties - surveyId = %s",
                keys.size(), surveyId));
        ds.delete(keys);
    }

}

@@ -793,37 +793,8 @@
 ys;%0A
-import java.util.Collection;%0A
 impo
@@ -1026,16 +1026,70 @@
 re.Key;%0A
+import com.google.appengine.api.datastore.KeyFactory;%0A
 import c
@@ -1784,24 +1784,212 @@
 %0A        %7D%0A%0A
+        Entity survey = ds.get(KeyFactory.createKey(%22Survey%22, surveyId));%0A        Long surveyGroupId = (Long) survey.getProperty(%22surveyGroupId%22);%0A        if (surveyGroupId != null) %7B%0A    
         dele
@@ -2011,28 +2011,43 @@
 e(ds, survey
-Id);
+GroupId);%0A        %7D
 %0A    %7D%0A%0A    
@@ -2780,32 +2780,37 @@
  ds, Long survey
+Group
 Id) %7B%0A        //
@@ -2811,83 +2811,99 @@
     
-// NOTE: It's not possible to query by the %60surveyInstanceContrib%60 property
+final Filter f = new FilterPredicate(%22surveyGroupId%22, FilterOperator.EQUAL, surveyGroupId);
 %0A   
@@ -2950,16 +2950,43 @@
 Locale%22)
+.setFilter(f).setKeysOnly()
 ;%0A      
@@ -3102,36 +3102,40 @@
 Entity e : pq.as
-List
+Iterable
 (FetchOptions.Bu
@@ -3167,198 +3167,8 @@
 ) %7B%0A
-            Collection%3CLong%3E contrib = (Collection%3CLong%3E) e.getProperty(%22surveyInstanceContrib%22);%0A            if (contrib != null && contrib.size() == 1 && contrib.contains(surveyId)) %7B%0A    
     
@@ -3201,22 +3201,8 @@
 ));%0A
-            %7D%0A
     
@@ -3248,16 +3248,33 @@
 .format(
+%0A                
 %22Surveye
@@ -3302,32 +3302,37 @@
  enties - survey
+Group
 Id = %25s%22,%0A      
@@ -3352,32 +3352,37 @@
 s.size(), survey
+Group
 Id));%0A        ds

Refactor data script to use the surveyGroupId for filtering SurveyedLocales