package com.truckmuncher.app.data.sync;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import com.truckmuncher.api.trucks.ServingModeRequest;
import com.truckmuncher.api.trucks.TruckService;
import com.truckmuncher.app.data.ApiException;
import com.truckmuncher.app.data.Contract;
import com.truckmuncher.app.data.PublicContract;
import com.truckmuncher.app.data.sql.WhereClause;
import static com.truckmuncher.app.data.Contract.suppressNotify;
import static com.truckmuncher.app.data.sql.WhereClause.Operator.EQUALS;
public final class TruckServingModeSyncTask extends SyncTask {
private final ContentProviderClient provider;
private final TruckService truckService;
private final ApiExceptionResolver apiExceptionResolver;
public TruckServingModeSyncTask(ContentProviderClient provider, TruckService truckService, ApiExceptionResolver apiExceptionResolver) {
this.provider = provider;
this.truckService = truckService;
this.apiExceptionResolver = apiExceptionResolver;
}
@Override
protected ApiResult sync(SyncResult syncResult) throws RemoteException {
WhereClause whereClause = new WhereClause.Builder()
.where(Contract.TruckState.IS_DIRTY, EQUALS, true)
.build();
Cursor cursor = provider.query(PublicContract.TRUCK_URI, TruckServingModeQuery.PROJECTION, whereClause.selection, whereClause.selectionArgs, null);
if (!cursor.moveToFirst()) {
// Cursor is empty. Probably already synced this.
cursor.close();
return ApiResult.OK;
}
ApiResult retVal = ApiResult.OK;
do {
ServingModeRequest request = new ServingModeRequest.Builder()
.isInServingMode(cursor.getInt(TruckServingModeQuery.IS_SERVING) == 1)
.truckId(cursor.getString(TruckServingModeQuery.ID))
.truckLatitude(cursor.getDouble(TruckServingModeQuery.LATITUDE))
.truckLongitude(cursor.getDouble(TruckServingModeQuery.LONGITUDE))
.build();
try {
truckService.modifyServingMode(request);
// Clear the dirty state
ContentValues values = new ContentValues();
values.put(Contract.TruckState.IS_DIRTY, false);
// Since we're clearing an internal state, don't notify listeners
Uri uri = suppressNotify(Contract.TRUCK_STATE_URI);
WhereClause q = new WhereClause.Builder()
.where(PublicContract.Truck.ID, EQUALS, request.truckId)
.build();
provider.update(uri, values, q.selection, q.selectionArgs);
} catch (ApiException e) {
ApiResult result = apiExceptionResolver.resolve(e);
// Need to use the most recoverable result
if (result == ApiResult.SHOULD_RETRY || retVal == ApiResult.SHOULD_RETRY) {
retVal = ApiResult.SHOULD_RETRY;
} else if (result == ApiResult.TEMPORARY_ERROR || retVal == ApiResult.TEMPORARY_ERROR) {
retVal = ApiResult.TEMPORARY_ERROR;
} else if (result == ApiResult.NEEDS_USER_INPUT || retVal == ApiResult.NEEDS_USER_INPUT) {
retVal = ApiResult.NEEDS_USER_INPUT;
} else if (result == ApiResult.PERMANENT_ERROR || retVal == ApiResult.PERMANENT_ERROR) {
retVal = ApiResult.PERMANENT_ERROR;
} else {
retVal = result;
}
}
} while (cursor.moveToNext());
cursor.close();
return retVal;
}
interface TruckServingModeQuery {
static final String[] PROJECTION = new String[]{
PublicContract.Truck.ID,
PublicContract.Truck.IS_SERVING,
PublicContract.Truck.LATITUDE,
PublicContract.Truck.LONGITUDE
};
static final int ID = 0;
static final int IS_SERVING = 1;
static final int LATITUDE = 2;
static final int LONGITUDE = 3;
}
}