package org.mercury_im.messenger.usecase; import org.mercury_im.messenger.data.repository.AccountRepository; import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.xmpp.MercuryConnection; import org.mercury_im.messenger.xmpp.MercuryConnectionManager; import java.util.logging.Level; import java.util.logging.Logger; import io.reactivex.Completable; import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; public class AddAccount { private static final Logger LOGGER = Logger.getLogger(AddAccount.class.getName()); private final AccountRepository accountRepository; private final MercuryConnectionManager connectionManager; private final CompositeDisposable disposable = new CompositeDisposable(); public AddAccount(AccountRepository accountRepository, MercuryConnectionManager connectionManager) { this.accountRepository = accountRepository; this.connectionManager = connectionManager; } public Completable execute(Account account) { return loginAndStoreAccountIfSuccessful(account); } private Completable loginAndStoreAccountIfSuccessful(Account account) { LOGGER.log(Level.INFO, "loginAndStoreIfSuccessful"); return logIntoAccount(account).flatMap(connection -> insertEnabledAccountIntoDatabase(account).flatMap(insertedAccount -> updateAccountIdInConnectionSingle(insertedAccount, connection))) .map(this::addConnectionToMessenger) .ignoreElement(); } private Single logIntoAccount(Account account) { return getOrCreateConnectionSingle(account) .doAfterSuccess(con -> LogIntoAccount.with(con).executeAndPossiblyThrow()) .subscribeOn(Schedulers.io()); } private Single getOrCreateConnectionSingle(Account account) { return Single.fromCallable(() -> getOrCreateConnection(account)); } private MercuryConnection getOrCreateConnection(Account account) { MercuryConnection connection = connectionManager.getConnection(account); if (connection == null) { connection = new MercuryConnection(accountRepository, account); } return connection; } private Single insertEnabledAccountIntoDatabase(Account account) { account.setEnabled(true); return accountRepository.upsertAccount(account); } private Completable addConnectionToMessenger(MercuryConnection connection) { return Completable.fromAction(() -> connectionManager.registerConnection(connection)); } private Single updateAccountIdInConnectionSingle(Account account, MercuryConnection connection) { return Single.fromCallable(() -> { updateAccountIdInConnection(account, connection); return connection; }); } private void updateAccountIdInConnection(Account account, MercuryConnection connection) { if (connection != null) { connection.getAccount().setId(account.getId()); } } }