Added Android code
[wl-app.git] / Android / app / src / main / java / com / moiseum / wolnelektury / view / search / BookSearchPresenter.java
1 package com.moiseum.wolnelektury.view.search;
2
3 import android.os.Bundle;
4 import android.os.Handler;
5
6 import com.moiseum.wolnelektury.R;
7 import com.moiseum.wolnelektury.base.WLApplication;
8 import com.moiseum.wolnelektury.base.mvp.FragmentPresenter;
9 import com.moiseum.wolnelektury.connection.RestClient;
10 import com.moiseum.wolnelektury.connection.RestClientCallback;
11 import com.moiseum.wolnelektury.connection.models.BookModel;
12 import com.moiseum.wolnelektury.connection.models.CategoryModel;
13 import com.moiseum.wolnelektury.connection.services.BooksService;
14 import com.moiseum.wolnelektury.utils.StringUtils;
15 import com.moiseum.wolnelektury.events.BookFavouriteEvent;
16 import com.moiseum.wolnelektury.view.search.dto.FilterDto;
17
18 import org.greenrobot.eventbus.EventBus;
19 import org.greenrobot.eventbus.Subscribe;
20 import org.greenrobot.eventbus.ThreadMode;
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import retrofit2.Call;
26
27 /**
28  * Created by piotrostrowski on 16.11.2017.
29  */
30
31 class BookSearchPresenter extends FragmentPresenter<BookSearchView> {
32
33         private static final String ONLY_LECTURES_SLUG = "only_lectures_slug";
34         private static final String HAS_AUDIOBOOK_SLUG = "has_audiobook_slug";
35         private static final long TWO_SECONDS = 2000;
36
37         private final String lectureFilterName;
38         private final String audiobookFilterName;
39
40         private RestClient client = WLApplication.getInstance().getRestClient();
41
42         private FilterDto filters;
43         private String lastKey;
44         private String searchQuery;
45         private String temporarySearchText;
46         private Integer clickedPosition;
47
48         private Call<List<BookModel>> currentCall;
49
50         private Handler searchHandler;
51         private Runnable searchHandlerRunnable = new Runnable() {
52                 @Override
53                 public void run() {
54                         searchQuery = temporarySearchText;
55                         loadBooks(true);
56                 }
57         };
58
59         BookSearchPresenter(BookSearchView view) {
60                 super(view);
61                 lectureFilterName = getView().getContext().getString(R.string.lectures);
62                 audiobookFilterName = getView().getContext().getString(R.string.audiobook);
63
64                 filters = new FilterDto();
65                 lastKey = null;
66                 searchQuery = null;
67         }
68
69         @Override
70         public void onViewCreated(Bundle savedInstanceState) {
71                 super.onViewCreated(savedInstanceState);
72                 loadBooks(true);
73                 EventBus.getDefault().register(this);
74         }
75
76         @Override
77         public void onDestroy() {
78                 super.onDestroy();
79                 if (currentCall != null) {
80                         currentCall.cancel();
81                 }
82                 if (searchHandler != null) {
83                         searchHandler.removeCallbacks(searchHandlerRunnable);
84                 }
85                 EventBus.getDefault().unregister(this);
86         }
87
88         @SuppressWarnings("unused")
89         @Subscribe(threadMode = ThreadMode.MAIN)
90         public void onFavouriteStateChanged(BookFavouriteEvent event) {
91                 getView().updateFavouriteState(event.getState(), clickedPosition);
92         }
93
94         void bookSelected(BookModel item, int position) {
95                 clickedPosition = position;
96                 getView().presentBookDetails(item.getSlug());
97         }
98
99         void updateFilters(FilterDto dto) {
100                 filters = dto;
101                 List<CategoryModel> flatteredFilters = new ArrayList<>();
102                 if (dto.isLecture()) {
103                         CategoryModel lectureModel = new CategoryModel();
104                         lectureModel.setName(lectureFilterName);
105                         lectureModel.setSlug(ONLY_LECTURES_SLUG);
106                         flatteredFilters.add(lectureModel);
107                 }
108                 if (dto.isAudiobook()) {
109                         CategoryModel audiobookModel = new CategoryModel();
110                         audiobookModel.setName(audiobookFilterName);
111                         audiobookModel.setSlug(HAS_AUDIOBOOK_SLUG);
112                         flatteredFilters.add(audiobookModel);
113                 }
114                 flatteredFilters.addAll(dto.getFilteredEpochs());
115                 flatteredFilters.addAll(dto.getFilteredGenres());
116                 flatteredFilters.addAll(dto.getFilteredKinds());
117                 getView().applyFilters(flatteredFilters);
118                 loadBooks(true);
119         }
120
121         void removeFilter(CategoryModel item) {
122                 if (ONLY_LECTURES_SLUG.equals(item.getSlug())) {
123                         filters.setLecture(false);
124                 } else if (HAS_AUDIOBOOK_SLUG.equals(item.getSlug())) {
125                         filters.setAudiobook(false);
126                 } else if (filters.getFilteredEpochs().contains(item)) {
127                         filters.getFilteredEpochs().remove(item);
128                 } else if (filters.getFilteredGenres().contains(item)) {
129                         filters.getFilteredGenres().remove(item);
130                 } else if (filters.getFilteredKinds().contains(item)) {
131                         filters.getFilteredKinds().remove(item);
132                 }
133                 loadBooks(true);
134         }
135
136         void onFiltersClicked() {
137                 getView().displayFiltersView(filters);
138         }
139
140         void clearFilters() {
141                 filters = new FilterDto();
142                 lastKey = null;
143                 loadBooks(true);
144         }
145
146         void loadMoreBooks(final String key) {
147                 lastKey = key;
148                 loadBooks(false);
149         }
150
151         void onSearchChosen(String query) {
152                 if (query.length() == 0) {
153                         query = null;
154                 }
155                 searchQuery = query;
156                 loadBooks(true);
157         }
158
159         void onSearchChanged(String newText) {
160                 if (searchHandler != null) {
161                         searchHandler.removeCallbacks(searchHandlerRunnable);
162                 }
163
164                 if (newText.length() == 0) {
165                         onSearchChosen(newText);
166                 } else {
167                         temporarySearchText = newText;
168                         searchHandler = new Handler();
169                         searchHandler.postDelayed(searchHandlerRunnable, TWO_SECONDS);
170                 }
171         }
172
173         void retryInitialLoad() {
174                 loadBooks(true);
175         }
176
177         private void loadBooks(final boolean reset) {
178                 if (reset) {
179                         lastKey = null;
180                         getView().setInitialProgressVisible(true);
181                 } else {
182                         getView().setLoadMoreProgressVisible(true);
183                 }
184                 currentCall = client.call(new RestClientCallback<List<BookModel>, BooksService>() {
185                         @Override
186                         public void onSuccess(List<BookModel> data) {
187                                 hideProgress();
188                                 getView().setData(data, reset);
189                         }
190
191                         @Override
192                         public void onFailure(Exception e) {
193                                 hideProgress();
194                                 getView().showError(e, false);
195                         }
196
197                         @Override
198                         public void onCancel() {
199                                 //nop
200                         }
201
202                         @Override
203                         public Call<List<BookModel>> execute(BooksService service) {
204                                 return service.getSearchBooks(searchQuery,
205                                                 StringUtils.joinSlugs(filters.getFilteredEpochs(), ","),
206                                                 StringUtils.joinSlugs(filters.getFilteredGenres(), ","),
207                                                 StringUtils.joinSlugs(filters.getFilteredKinds(), ","),
208                                                 filters.isAudiobook() ? true : null,
209                                                 filters.isLecture() ? true : null,
210                                                 lastKey,
211                                                 RestClient.PAGINATION_LIMIT);
212                         }
213
214                         private void hideProgress() {
215                                 if (reset) {
216                                         getView().setInitialProgressVisible(false);
217                                 } else {
218                                         getView().setLoadMoreProgressVisible(false);
219                                 }
220                         }
221                 }, BooksService.class);
222         }
223 }