--- /dev/null
+package com.moiseum.wolnelektury.view.book.list;
+
+import android.os.Bundle;
+
+import com.moiseum.wolnelektury.base.DataObserver;
+import com.moiseum.wolnelektury.base.DataProvider;
+import com.moiseum.wolnelektury.base.WLApplication;
+import com.moiseum.wolnelektury.base.mvp.FragmentPresenter;
+import com.moiseum.wolnelektury.connection.downloads.FileCacheUtils;
+import com.moiseum.wolnelektury.connection.models.BookModel;
+import com.moiseum.wolnelektury.connection.services.BooksService;
+import com.moiseum.wolnelektury.storage.BookStorage;
+import com.moiseum.wolnelektury.events.BookFavouriteEvent;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import io.reactivex.Completable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * @author golonkos
+ */
+
+class BooksListPresenter extends FragmentPresenter<BooksListView> {
+
+ private static final String TAG = BooksListPresenter.class.getSimpleName();
+
+ private final DataProvider<List<BookModel>, BooksService> dataProvider;
+ private BookStorage storage;
+ private final BookListType bookListType;
+ private String lastKey;
+ private Integer clickedPosition;
+
+ BooksListPresenter(BooksListView view, BookListType type) {
+ super(view);
+ bookListType = type;
+ lastKey = null;
+ dataProvider = type.getDataProvider();
+ dataProvider.setDataObserver(new BooksListDataObserver());
+ storage = WLApplication.getInstance().getBookStorage();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ EventBus.getDefault().register(this);
+ }
+
+ @Override
+ public void onViewCreated(Bundle savedInstanceState) {
+ super.onViewCreated(savedInstanceState);
+ loadBooks();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ dataProvider.cancel();
+ EventBus.getDefault().unregister(this);
+ }
+
+ @SuppressWarnings("unused")
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onBookAdded(BookStorage.BookAddedEvent event) {
+ if (bookListType == BookListType.DOWNLOADED) {
+ reloadBooks();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onBookDeleted(BookStorage.BookDeletedEvent event) {
+ if (bookListType == BookListType.DOWNLOADED) {
+ reloadBooks();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onFavouriteStateChanged(BookFavouriteEvent event) {
+ // TODO: Change that full reload
+ if (bookListType == BookListType.FAVOURITES) {
+ reloadBooks();
+ } else {
+ getView().updateFavouriteState(event.getState(), clickedPosition);
+ }
+ }
+
+ public void reloadBooks() {
+ lastKey = null;
+ getView().clearList();
+ loadBooks();
+ }
+
+ public void loadMoreBooks() {
+ if (bookListType.isPageable()) {
+ loadBooks();
+ }
+ }
+
+ private void loadBooks() {
+ dataProvider.load(lastKey);
+ }
+
+ void onBookClicked(BookModel book, int position) {
+ clickedPosition = position;
+ getView().openBookDetailsView(book.getSlug());
+ }
+
+ void onBookDeleteClicked(BookModel book) {
+ BookModel downloadedBook = storage.find(book.getSlug());
+
+ List<Completable> deletionOperations = new ArrayList<>();
+ if (downloadedBook != null && downloadedBook.isEbookDownloaded()) {
+ deletionOperations.add(FileCacheUtils.deleteEbookFile(downloadedBook.getEbookFileUrl()));
+ }
+ if (downloadedBook != null && downloadedBook.isAudioDownloaded()) {
+ deletionOperations.add(FileCacheUtils.deleteAudiobookFiles(downloadedBook.getAudioFileUrls()));
+ }
+
+ storage.remove(book.getSlug(), false);
+ addDisposable(Completable.concat(deletionOperations).andThen(Completable.fromAction(() -> {
+ })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(() -> getView().updateEmptyViewVisibility(), error -> {
+ getView().showError(new Exception(error));
+ //restore books
+ loadBooks();
+ }));
+ }
+
+ private class BooksListDataObserver implements DataObserver<List<BookModel>> {
+
+ private List<BookModel> matchDownloadedBooks(List<BookModel> books) {
+ if (bookListType.isDeletable()) {
+ List<BookModel> merged = new ArrayList<>(books.size());
+ List<BookModel> downloadedBooks = storage.all();
+
+ for (BookModel book : books) {
+ boolean found = false;
+ for (BookModel downloaded : downloadedBooks) {
+ if (book.getSlug().equals(downloaded.getSlug())) {
+ merged.add(downloaded);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ merged.add(book);
+ }
+ }
+ return merged;
+ } else {
+ return books;
+ }
+ }
+
+ @Override
+ public void onLoadStarted() {
+ getView().setProgressVisible(true);
+ }
+
+ @Override
+ public void onLoadSuccess(List<BookModel> data) {
+ if (data.size() > 0) {
+ lastKey = data.get(data.size() - 1).getSortedKey();
+ data = matchDownloadedBooks(data);
+ }
+ getView().setProgressVisible(false);
+ getView().setData(data);
+ }
+
+ @Override
+ public void onLoadFailed(Exception e) {
+ getView().setProgressVisible(false);
+ getView().setData(Collections.emptyList());
+ getView().showError(e);
+ }
+ }
+}