Added Android code
[wl-app.git] / Android / app / src / main / java / com / moiseum / wolnelektury / view / book / list / BooksListPresenter.java
1 package com.moiseum.wolnelektury.view.book.list;
2
3 import android.os.Bundle;
4
5 import com.moiseum.wolnelektury.base.DataObserver;
6 import com.moiseum.wolnelektury.base.DataProvider;
7 import com.moiseum.wolnelektury.base.WLApplication;
8 import com.moiseum.wolnelektury.base.mvp.FragmentPresenter;
9 import com.moiseum.wolnelektury.connection.downloads.FileCacheUtils;
10 import com.moiseum.wolnelektury.connection.models.BookModel;
11 import com.moiseum.wolnelektury.connection.services.BooksService;
12 import com.moiseum.wolnelektury.storage.BookStorage;
13 import com.moiseum.wolnelektury.events.BookFavouriteEvent;
14
15 import org.greenrobot.eventbus.EventBus;
16 import org.greenrobot.eventbus.Subscribe;
17 import org.greenrobot.eventbus.ThreadMode;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import io.reactivex.Completable;
24 import io.reactivex.android.schedulers.AndroidSchedulers;
25 import io.reactivex.schedulers.Schedulers;
26
27 /**
28  * @author golonkos
29  */
30
31 class BooksListPresenter extends FragmentPresenter<BooksListView> {
32
33         private static final String TAG = BooksListPresenter.class.getSimpleName();
34
35         private final DataProvider<List<BookModel>, BooksService> dataProvider;
36         private BookStorage storage;
37         private final BookListType bookListType;
38         private String lastKey;
39         private Integer clickedPosition;
40
41         BooksListPresenter(BooksListView view, BookListType type) {
42                 super(view);
43                 bookListType = type;
44                 lastKey = null;
45                 dataProvider = type.getDataProvider();
46                 dataProvider.setDataObserver(new BooksListDataObserver());
47                 storage = WLApplication.getInstance().getBookStorage();
48         }
49
50         @Override
51         public void onCreate(Bundle savedInstanceState) {
52                 super.onCreate(savedInstanceState);
53                 EventBus.getDefault().register(this);
54         }
55
56         @Override
57         public void onViewCreated(Bundle savedInstanceState) {
58                 super.onViewCreated(savedInstanceState);
59                 loadBooks();
60         }
61
62         @Override
63         public void onDestroy() {
64                 super.onDestroy();
65                 dataProvider.cancel();
66                 EventBus.getDefault().unregister(this);
67         }
68
69         @SuppressWarnings("unused")
70         @Subscribe(threadMode = ThreadMode.MAIN)
71         public void onBookAdded(BookStorage.BookAddedEvent event) {
72                 if (bookListType == BookListType.DOWNLOADED) {
73                         reloadBooks();
74                 }
75         }
76
77         @SuppressWarnings("unused")
78         @Subscribe(threadMode = ThreadMode.MAIN)
79         public void onBookDeleted(BookStorage.BookDeletedEvent event) {
80                 if (bookListType == BookListType.DOWNLOADED) {
81                         reloadBooks();
82                 }
83         }
84
85         @SuppressWarnings("unused")
86         @Subscribe(threadMode = ThreadMode.MAIN)
87         public void onFavouriteStateChanged(BookFavouriteEvent event) {
88                 // TODO: Change that full reload
89                 if (bookListType == BookListType.FAVOURITES) {
90                         reloadBooks();
91                 } else {
92                         getView().updateFavouriteState(event.getState(), clickedPosition);
93                 }
94         }
95
96         public void reloadBooks() {
97                 lastKey = null;
98                 getView().clearList();
99                 loadBooks();
100         }
101
102         public void loadMoreBooks() {
103                 if (bookListType.isPageable()) {
104                         loadBooks();
105                 }
106         }
107
108         private void loadBooks() {
109                 dataProvider.load(lastKey);
110         }
111
112         void onBookClicked(BookModel book, int position) {
113                 clickedPosition = position;
114                 getView().openBookDetailsView(book.getSlug());
115         }
116
117         void onBookDeleteClicked(BookModel book) {
118                 BookModel downloadedBook = storage.find(book.getSlug());
119
120                 List<Completable> deletionOperations = new ArrayList<>();
121                 if (downloadedBook != null && downloadedBook.isEbookDownloaded()) {
122                         deletionOperations.add(FileCacheUtils.deleteEbookFile(downloadedBook.getEbookFileUrl()));
123                 }
124                 if (downloadedBook != null && downloadedBook.isAudioDownloaded()) {
125                         deletionOperations.add(FileCacheUtils.deleteAudiobookFiles(downloadedBook.getAudioFileUrls()));
126                 }
127
128                 storage.remove(book.getSlug(), false);
129                 addDisposable(Completable.concat(deletionOperations).andThen(Completable.fromAction(() -> {
130                 })).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(() -> getView().updateEmptyViewVisibility(), error -> {
131                         getView().showError(new Exception(error));
132                         //restore books
133                         loadBooks();
134                 }));
135         }
136
137         private class BooksListDataObserver implements DataObserver<List<BookModel>> {
138
139                 private List<BookModel> matchDownloadedBooks(List<BookModel> books) {
140                         if (bookListType.isDeletable()) {
141                                 List<BookModel> merged = new ArrayList<>(books.size());
142                                 List<BookModel> downloadedBooks = storage.all();
143
144                                 for (BookModel book : books) {
145                                         boolean found = false;
146                                         for (BookModel downloaded : downloadedBooks) {
147                                                 if (book.getSlug().equals(downloaded.getSlug())) {
148                                                         merged.add(downloaded);
149                                                         found = true;
150                                                         break;
151                                                 }
152                                         }
153                                         if (!found) {
154                                                 merged.add(book);
155                                         }
156                                 }
157                                 return merged;
158                         } else {
159                                 return books;
160                         }
161                 }
162
163                 @Override
164                 public void onLoadStarted() {
165                         getView().setProgressVisible(true);
166                 }
167
168                 @Override
169                 public void onLoadSuccess(List<BookModel> data) {
170                         if (data.size() > 0) {
171                                 lastKey = data.get(data.size() - 1).getSortedKey();
172                                 data = matchDownloadedBooks(data);
173                         }
174                         getView().setProgressVisible(false);
175                         getView().setData(data);
176                 }
177
178                 @Override
179                 public void onLoadFailed(Exception e) {
180                         getView().setProgressVisible(false);
181                         getView().setData(Collections.emptyList());
182                         getView().showError(e);
183                 }
184         }
185 }