package com.truckmuncher.app.menu; import android.app.Service; import android.content.ContentValues; import android.content.Intent; import android.location.Location; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; import android.support.annotation.NonNull; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.truckmuncher.api.menu.Category; import com.truckmuncher.api.menu.FullMenusRequest; import com.truckmuncher.api.menu.FullMenusResponse; import com.truckmuncher.api.menu.Menu; import com.truckmuncher.api.menu.MenuItem; import com.truckmuncher.api.menu.MenuService; import com.truckmuncher.app.App; import com.truckmuncher.app.data.PublicContract; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import retrofit.Callback; import retrofit.RetrofitError; import retrofit.client.Response; import timber.log.Timber; public class MenuUpdateService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { @Inject MenuService menuService; private GoogleApiClient apiClient; @Override public void onCreate() { super.onCreate(); App.get(this).inject(this); apiClient = new GoogleApiClient.Builder(this, this, this) .addApi(LocationServices.API) .build(); apiClient.connect(); } @Override public void onDestroy() { super.onDestroy(); apiClient.disconnect(); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onConnected(Bundle bundle) { Location location = LocationServices.FusedLocationApi.getLastLocation(apiClient); if (location != null) { doUpdate(location); } else { LocationRequest request = new LocationRequest() .setPriority(LocationRequest.PRIORITY_LOW_POWER) // City level .setInterval(5000); // 5 seconds. We want it quickly b/c we'll stop w/ location right away, but might need ot update UI LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, request, this); } } @Override public void onConnectionSuspended(int i) { // TODO Handle } @Override public void onConnectionFailed(ConnectionResult connectionResult) { stopSelf(); } @Override public void onLocationChanged(Location location) { if (location != null) { LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this); doUpdate(location); } } private void doUpdate(@NonNull Location location) { FullMenusRequest request = new FullMenusRequest.Builder() .includeAvailability(true) .latitude(location.getLatitude()) .longitude(location.getLongitude()) .build(); menuService.getFullMenus(request, new Callback<FullMenusResponse>() { @Override public void success(final FullMenusResponse fullMenusResponse, Response response) { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { List<Menu> menus = fullMenusResponse.menus; List<ContentValues> categoryContentValues = new ArrayList<>(); List<ContentValues> menuItemContentValues = new ArrayList<>(); for (Menu menu : menus) { List<Category> categories = menu.categories; for (Category category : categories) { ContentValues categoryValues = new ContentValues(); categoryValues.put(PublicContract.Category.ID, category.id); categoryValues.put(PublicContract.Category.NAME, category.name); categoryValues.put(PublicContract.Category.NOTES, category.notes); categoryValues.put(PublicContract.Category.ORDER_IN_MENU, category.orderInMenu); categoryValues.put(PublicContract.Category.TRUCK_ID, menu.truckId); categoryContentValues.add(categoryValues); List<MenuItem> menuItems = category.menuItems; for (MenuItem item : menuItems) { ContentValues itemValues = new ContentValues(); itemValues.put(PublicContract.MenuItem.ID, item.id); itemValues.put(PublicContract.MenuItem.IS_AVAILABLE, item.isAvailable); itemValues.put(PublicContract.MenuItem.PRICE, item.price); itemValues.put(PublicContract.MenuItem.ORDER_IN_CATEGORY, item.orderInCategory); itemValues.put(PublicContract.MenuItem.NOTES, item.notes); itemValues.put(PublicContract.MenuItem.NAME, item.name); itemValues.put(PublicContract.MenuItem.TAGS, PublicContract.convertListToString(item.tags)); itemValues.put(PublicContract.MenuItem.CATEGORY_ID, category.id); menuItemContentValues.add(itemValues); } } } ContentValues[] categoryInsert = categoryContentValues.toArray(new ContentValues[categoryContentValues.size()]); ContentValues[] menuItemInsert = menuItemContentValues.toArray(new ContentValues[menuItemContentValues.size()]); getContentResolver().bulkInsert(PublicContract.CATEGORY_URI, categoryInsert); getContentResolver().bulkInsert(PublicContract.MENU_ITEM_URI, menuItemInsert); return null; } @Override protected void onPostExecute(Void aVoid) { // Need to notify on the Menu View URI b/c ContentProvider won't getContentResolver().notifyChange(PublicContract.MENU_URI, null); stopSelf(); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @Override public void failure(RetrofitError error) { // All logging has already been performed at this point. Timber.e("Got an error while getting full menus."); stopSelf(); } }); } }