content: package com.google.firebase.example.fireeats.util;
  
  import android.content.Context;
  import android.support.annotation.WorkerThread;
  
  import com.google.android.gms.tasks.Task;
  import com.google.android.gms.tasks.Tasks;
  import com.google.firebase.example.fireeats.R;
  import com.google.firebase.example.fireeats.model.Restaurant;
  import com.google.firebase.firestore.CollectionReference;
  import com.google.firebase.firestore.DocumentSnapshot;
  import com.google.firebase.firestore.Query;
  import com.google.firebase.firestore.QuerySnapshot;
  import com.google.firebase.firestore.WriteBatch;
  
  import java.util.Arrays;
  import java.util.List;
  import java.util.Locale;
  import java.util.Random;
  import java.util.concurrent.Executor;
  import java.util.concurrent.LinkedBlockingQueue;
  import java.util.concurrent.ThreadPoolExecutor;
  import java.util.concurrent.TimeUnit;
  
  /**
   * Utilities for Restaurants.
   */
  public class RestaurantUtil {
  
      private static final String TAG = "RestaurantUtil";
  
      private static final ThreadPoolExecutor EXECUTOR =
              new ThreadPoolExecutor(2, 4, 60,
                      TimeUnit.SECONDS, new LinkedBlockingQueue<>());
  
      private static final String RESTAURANT_URL_FMT = "https://storage.googleapis.com/firestorequickstarts.appspot.com/food_%d.png";
      private static final int MAX_IMAGE_NUM = 22;
  
      private static final String[] NAME_FIRST_WORDS = {
              "Foo",
              "Bar",
              "Baz",
              "Qux",
              "Fire",
              "Sam's",
              "World Famous",
              "Google",
              "The Best",
      };
  
      private static final String[] NAME_SECOND_WORDS = {
              "Restaurant",
              "Cafe",
              "Spot",
              "Eatin' Place",
              "Eatery",
              "Drive Thru",
              "Diner",
      };
  
  
      /**
       * Create a random Restaurant POJO.
       */
      public static Restaurant getRandom(Context context) {
          Restaurant restaurant = new Restaurant();
          Random random = new Random();
  
          // Cities (first elemnt is 'Any')
          String[] cities = context.getResources().getStringArray(R.array.cities);
          cities = Arrays.copyOfRange(cities, 1, cities.length);
  
          // Categories (first element is 'Any')
          String[] categories = context.getResources().getStringArray(R.array.categories);
          categories = Arrays.copyOfRange(categories, 1, categories.length);
  
          int[] prices = new int[]{1, 2, 3};
  
          restaurant.name = getRandomName(random);
          restaurant.city = getRandomString(cities, random);
          restaurant.category = getRandomString(categories, random);
          restaurant.photo = getRandomImageUrl(random);
          restaurant.price = getRandomInt(prices, random);
          restaurant.numRatings = random.nextInt(20);
  
          // Note: average rating intentionally not set
  
          return restaurant;
      }
  
  
      /**
       * Get a random image.
       */
      private static String getRandomImageUrl(Random random) {
          // Integer between 1 and MAX_IMAGE_NUM (inclusive)
          int id = random.nextInt(MAX_IMAGE_NUM) + 1;
  
          return String.format(Locale.getDefault(), RESTAURANT_URL_FMT, id);
      }
  
      /**
       * Get price represented as dollar signs.
       */
      public static String getPriceString(Restaurant restaurant) {
          return restaurant != null ? getPriceString(restaurant.price) : null;
      }
  
      /**
       * Get price represented as dollar signs.
       */
      public static String getPriceString(int priceInt) {
          switch (priceInt) {
              case 1:
                  return "$";
              case 2:
                  return "$$";
              case 3:
              default:
                  return "$$$";
          }
      }
  
      /**
       * Delete all documents in a collection. Uses an Executor to perform work on a background
       * thread. This does *not* automatically discover and delete subcollections.
       */
      private static Task<Void> deleteCollection(final CollectionReference collection,
                                                 final int batchSize,
                                                 Executor executor) {
  
          // Perform the delete operation on the provided Executor, which allows us to use
          // simpler synchronous logic without blocking the main thread.
          return Tasks.call(executor, () -> {
              // Get the first batch of documents in the collection
              Query query = collection.orderBy("__name__").limit(batchSize);
  
              // Get a list of deleted documents
              List<DocumentSnapshot> deleted = deleteQueryBatch(query);
  
              // While the deleted documents in the last batch indicate that there
              // may still be more documents in the collection, page down to the
              // next batch and delete again
              while (deleted.size() >= batchSize) {
                  // Move the query cursor to start after the last doc in the batch
                  DocumentSnapshot last = deleted.get(deleted.size() - 1);
                  query = collection.orderBy("__name__")
                          .startAfter(last.getId())
                          .limit(batchSize);
  
                  deleted = deleteQueryBatch(query);
              }
  
              return null;
          });
  
      }
  
      /**
       * Delete all results from a query in a single WriteBatch. Must be run on a worker thread
       * to avoid blocking/crashing the main thread.
       */
      @WorkerThread
      private static List<DocumentSnapshot> deleteQueryBatch(final Query query) throws Exception {
          QuerySnapshot querySnapshot = Tasks.await(query.get());
  
          WriteBatch batch = query.getFirestore().batch();
          for (DocumentSnapshot snapshot : querySnapshot) {
              batch.delete(snapshot.getReference());
          }
          Tasks.await(batch.commit());
  
          return querySnapshot.getDocuments();
      }
  
      /**
       * Delete all restaurants.
       */
      public static Task<Void> deleteAll(final CollectionReference ref) {
          return deleteCollection(ref, 25, EXECUTOR);
      }
  
      private static double getRandomRating(Random random) {
          double min = 1.0;
          return min + (random.nextDouble() * 4.0);
      }
  
      private static String getRandomName(Random random) {
          return getRandomString(NAME_FIRST_WORDS, random) + " "
                  + getRandomString(NAME_SECOND_WORDS, random);
      }
  
      private static String getRandomString(String[] array, Random random) {
          int ind = random.nextInt(array.length);
          return array[ind];
      }
  
      private static int getRandomInt(int[] array, Random random) {
          int ind = random.nextInt(array.length);
          return array[ind];
      }
  
  }
  