package it.niedermann.nextcloud.deck.persistence.sync; import android.app.Activity; import android.arch.lifecycle.LiveData; import android.content.Context; import android.content.SharedPreferences; import java.util.ArrayList; import java.util.Date; import java.util.List; import it.niedermann.nextcloud.deck.DeckConsts; import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.api.IResponseCallback; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.model.Board; import it.niedermann.nextcloud.deck.model.Card; import it.niedermann.nextcloud.deck.model.Label; import it.niedermann.nextcloud.deck.model.Stack; import it.niedermann.nextcloud.deck.model.User; import it.niedermann.nextcloud.deck.model.interfaces.RemoteEntity; import it.niedermann.nextcloud.deck.persistence.sync.adapters.IDataBasePersistenceAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.IPersistenceAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.ServerAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.IDatabaseOnlyAdapter; public class SyncManager implements IDataBasePersistenceAdapter { private IDatabaseOnlyAdapter dataBaseAdapter; private IPersistenceAdapter serverAdapter; private Context applicationContext; private Activity sourceActivity; public SyncManager(Context applicationContext, Activity sourceActivity) { this.applicationContext = applicationContext.getApplicationContext(); this.sourceActivity = sourceActivity; dataBaseAdapter = new DataBaseAdapter(this.applicationContext); this.serverAdapter = new ServerAdapter(this.applicationContext, sourceActivity); } private void doAsync(Runnable r) { new Thread(r).start(); } public void synchronize(IResponseCallback responseCallback) { final long accountId = responseCallback.getAccount().getId(); doAsync(() -> { SharedPreferences lastSyncPref = applicationContext.getSharedPreferences( applicationContext.getString(R.string.shared_preference_last_sync), Context.MODE_PRIVATE); long lastSync = lastSyncPref.getLong(DeckConsts.LAST_SYNC_KEY, 0L); Date lastSyncDate = new Date(lastSync); Date now = new Date(); // welcome to the Call-Pyramid from Hell serverAdapter.getBoards(accountId, new IResponseCallback>(responseCallback.getAccount()) { @Override public void onResponse(List response) { for (Board b : response) { Board existingBoard = dataBaseAdapter.getBoard(accountId, b.getId()); if (existingBoard == null) { dataBaseAdapter.createBoard(accountId, b); } else { dataBaseAdapter.updateBoard(applyUpdatesFromRemote(existingBoard, b, accountId)); } synchronizeStacksOf(b, responseCallback); } responseCallback.onResponse(true); } @Override public void onError(Throwable throwable) { responseCallback.onError(throwable); } }); //TODO activate when done dev // lastSyncPref.edit().putLong(LAST_SYNC_KEY, now.getTime()).apply(); }); } private void synchronizeStacksOf(final Board board, final IResponseCallback responseCallback) { //sync stacks Account account = responseCallback.getAccount(); long accountId = account.getId(); final Board syncedBoard = dataBaseAdapter.getBoard(accountId, board.getId()); serverAdapter.getStacks(accountId, board.getId(), new IResponseCallback>(account) { @Override public void onResponse(List response) { for (Stack stack : response) { stack.setBoardId(syncedBoard.getLocalId()); Stack existingStack = dataBaseAdapter.getStack(accountId, syncedBoard.getLocalId(), stack.getId()); if (existingStack == null) { dataBaseAdapter.createStack(accountId, stack); } else { dataBaseAdapter.updateStack(applyUpdatesFromRemote(existingStack, stack, accountId)); } existingStack = dataBaseAdapter.getStack(accountId, syncedBoard.getLocalId(), stack.getId()); dataBaseAdapter.deleteJoinedCardsForStack(existingStack.getLocalId()); synchronizeCardOf(stack, syncedBoard, responseCallback); } //responseCallback.onResponse(true); } @Override public void onError(Throwable throwable) { responseCallback.onError(throwable); } }); } private void synchronizeCardOf(final Stack stack, final Board syncedBoard, final IResponseCallback responseCallback) { //sync cards Account account = responseCallback.getAccount(); long accountId = account.getId(); Stack syncedStack = dataBaseAdapter.getStack(accountId, syncedBoard.getLocalId(), stack.getId()); for (Card c : stack.getCards()) { DeckLog.log("requesting Card: " + c.getTitle()); serverAdapter.getCard(accountId, syncedBoard.getId(), syncedStack.getId(), c.getId(), new IResponseCallback(account) { @Override public void onResponse(Card card) { List assignedUsers = card.getAssignedUsers(); List