package com.rapidftr.task; import android.app.Notification; import android.app.NotificationManager; import android.os.AsyncTask; import android.util.Log; import android.widget.Toast; import com.rapidftr.R; import com.rapidftr.RapidFtrApplication; import com.rapidftr.activity.RapidFtrActivity; import com.rapidftr.model.BaseModel; import com.rapidftr.model.User; import com.rapidftr.repository.Repository; import com.rapidftr.service.FormService; import com.rapidftr.service.SyncService; import lombok.Setter; import org.apache.http.HttpException; import org.json.JSONException; import java.io.IOException; import java.util.List; import java.util.Random; public abstract class SynchronisationAsyncTask<T extends BaseModel> extends AsyncTask<Object, String, Boolean> { public static int NOTIFICATION_ID = 1010 + new Random().nextInt(10); private static final String SYNC_ALL = "SYNC_ALL"; private static final String CANCEL_SYNC_ALL = "CANCEL_SYNC_ALL"; protected FormService formService; protected SyncService<T> recordSyncService; protected Repository<T> repository; protected User currentUser; protected RapidFtrActivity context; protected Notification notification; protected NotificationManager notificationManager; protected int formSectionProgress; protected int maxProgress; @Setter private String successMessage = "Records Successfully Synchronized"; public SynchronisationAsyncTask(FormService formService, SyncService<T> recordSyncService, Repository<T> repository, User user) { this.formService = formService; this.recordSyncService = recordSyncService; this.repository = repository; currentUser = user; } @Override protected void onPreExecute() { RapidFtrApplication.getApplicationInstance().setSyncTask(this); toggleMenu(CANCEL_SYNC_ALL); } @Override protected Boolean doInBackground(Object... notRelevant) { try { sync(); return true; } catch (HttpException e) { Log.e("SyncAllDataTask", "HTTPError in sync", e); String message = RapidFtrApplication.getApplicationInstance().getString(R.string.session_timeout); if (e.getMessage() != null && e.getMessage().trim().length() > 0) { message = e.getMessage(); } publishProgress(message); return false; } catch (Exception e) { Log.e("SyncAllDataTask", "Error in sync", e); publishProgress(e.getMessage()); return false; } } protected abstract void sync() throws JSONException, IOException, HttpException; protected void getFormSections() throws IOException { if (!isCancelled()) { formService.downloadPublishedFormSections(); } } void setProgressBarParameters(List<String> idsToDownload, List<?> recordsToSyncWithServer) { int totalRecordsToSynchronize = idsToDownload.size() + recordsToSyncWithServer.size(); formSectionProgress = totalRecordsToSynchronize / 4 == 0 ? 20 : totalRecordsToSynchronize / 4; maxProgress = totalRecordsToSynchronize + formSectionProgress; } @Override protected void onProgressUpdate(String... values) { RapidFtrApplication.getApplicationInstance().showNotification(recordSyncService.getNotificationId(), recordSyncService.getNotificationTitle(), values[0]); } @Override protected void onPostExecute(Boolean result) { toggleMenu(SYNC_ALL); RapidFtrApplication.getApplicationInstance().setSyncTask(null); if (result) { RapidFtrApplication.getApplicationInstance().showNotification(recordSyncService.getNotificationId(), recordSyncService.getNotificationTitle(), successMessage); Toast.makeText(RapidFtrApplication.getApplicationInstance(), successMessage, Toast.LENGTH_LONG).show(); } else { Toast.makeText(RapidFtrApplication.getApplicationInstance(), RapidFtrApplication.getApplicationInstance().getString(R.string.sync_error), Toast.LENGTH_LONG).show(); } } @Override protected void onCancelled() { toggleMenu(SYNC_ALL); RapidFtrApplication.getApplicationInstance().cancelNotification(recordSyncService.getNotificationId()); RapidFtrApplication.getApplicationInstance().setSyncTask(null); } private void toggleMenu(String showMenu) { context.getMenu().getItem(0).setVisible(showMenu.equals(SYNC_ALL)); context.getMenu().getItem(1).setVisible(showMenu.equals(CANCEL_SYNC_ALL)); } protected void setProgressAndNotify(String statusText, int progress) { if (!isCancelled()) { RapidFtrApplication.getApplicationInstance().showProgressNotification(recordSyncService.getNotificationId(), context.getString(R.string.sync_title), statusText, maxProgress, progress, false); } } void sendRecordsToServer(List<T> recordsToSyncWithServer) throws IOException, JSONException, HttpException { setProgressAndNotify(context.getString(R.string.synchronize_step_2), formSectionProgress); String subStatusFormat = "Uploading Record %s of " + recordsToSyncWithServer.size(); int counter = 0; int startProgress = formSectionProgress; for (T baseModel : recordsToSyncWithServer) { if (isCancelled()) { break; } recordSyncService.sync(baseModel, currentUser); setProgressAndNotify(String.format(subStatusFormat, ++counter), startProgress); startProgress += 1; } } protected void saveIncomingRecords(List<String> idsToDownload, int startProgress) throws IOException, JSONException, HttpException { String subStatusFormat = "Downloading Record %s of" + idsToDownload.size(); int counter = 0; setProgressAndNotify(context.getString(R.string.synchronize_step_3), startProgress); for (String idToDownload : idsToDownload) { T incomingRecord = recordSyncService.getRecord(idToDownload); if (isCancelled()) { break; } try { repository.createOrUpdateWithoutHistory(incomingRecord); recordSyncService.setMedia(incomingRecord); recordSyncService.setLastSyncedAt(incomingRecord); setProgressAndNotify(String.format(subStatusFormat, ++counter), startProgress); startProgress += 1; } catch (Exception e) { Log.e("SyncAllDataTask", "Error syncing record", e); throw new RuntimeException(e); } } } public void setContext(RapidFtrActivity context) { this.context = context; } }